You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ab...@apache.org on 2020/03/17 17:20:56 UTC

[nifi-registry] branch NIFIREG-371-RC1 created (now 511b886)

This is an automated email from the ASF dual-hosted git repository.

aboda pushed a change to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git.


      at 511b886  Fix docker maven files

This branch includes the following new commits:

     new eeb8621  NIFIREG-314 Remove reference to HipChat from README
     new 9f4012d  NIFIREG-293 Highlight in Getting Started guide that only process groups can be versioned
     new 75b188a  Update .travis.yml
     new 1bc729d  NIFIREG-317 Improve logging for errors that occur when creating providers
     new ff54171  NIFIREG-318 Change bootstrap port command handling
     new 32c1341  NIFIREG-320 - Added jetty header filters to set security headers. Setting security headers for the registry-api using spring security configuration. NIFIREG-320 - Fixed rest-api docs loading. Headers confirmed to be applied for docs. NIFIREG-320 - Removed unnecessary dependency.
     new 17dcc77  NIFIREG-323 Clear secret key when auto restarting in order to obtain new secret key from the NiFi Registry process
     new 25625cd  [NIFIREG-319] remove code coverage instrumentation from nifi-fds js modules
     new 1be492f  NIFIREG-325: support for node identity group - updated admin guide - adjusting PR / fixing issues found during review
     new 7e2f120  NIFIREG-327 Added section on recommended antivirus exclusions to Admin Guide
     new b2f6307  [NIFIREG-297] Upgrade to latest LTS release of Node (and npm)
     new 9849f85  NIFIREG-336 Enable Integration Tests by Default
     new e171ba9  NIFIREG-329 Add build profile that tests all DBs
     new 219b57c  NIFIREG-337 Add automated testing for Postgres 10.x
     new 6a3dbd2  NIFIREG-338: fixing version in dockerfile
     new a503ba1  NIFIREG-334 Changes to support Java 11 - Upgrade Groovy to 2.5.x - Setup jigsaw profile to optionally include Java 11 dependencies - Modify assembly to create lib/java11 dir - Modify RunNiFiRegistry to optionally add lib/java11 to the classpath - Modify OSUtils to correctly handle PIDs when running on Java 11 - Update assembly LICENSE to include Jakarta artifacts under EDL - Updating Travis config to include a Java 11 build
     new ba0555f  NIFIREG-339 Remove errors from root pom
     new 74baaa9  NIFIREG-341 Make use of ASF shortened URL to point to community Slack invite link.
     new 5cb04c6  [NIFIREG-324] add hammerJS to testbed
     new 35bcf43  NIFIREG-252: adding mavendocker as build profile
     new 5e66a21  NIFIREG-345 Bump ranger-client version to 2.0.0
     new 3cca3ea  [NIFIREG-352] update frontend deps
     new bb3b291  update package-lock
     new 859b75e  NIFIREG-354 - updated toString to allow for null snapshot metadata, which can happen when using this class to represent an unversioned flow outside of the NiFi Registry context
     new dab4b5f  NIFIREG-355 Adding profiles to optionally include addtional hadoop libs in ext/ranger/lib
     new 23afadf  NIFIREG-353 Add ShellUserGroupProvider and relax checks to allow a user to have same identity as a group
     new 7bbe1fa  NIFIREG-356 Fixing additional classpath resources for Authorizers and ensuring proper context ClassLoader is set
     new cc47296  NIFIREG-357 Added autocomplete="off" to login password input.
     new f1e4fb2  [NIFIREG-352] update frontend deps
     new b4a482b  update package-lock
     new 46bb1aa  NIFIREG-362 - Updated dependencies and ran tests. Smoke tested NiFi and NiFi Reg in secured instances.
     new 553fe65  Fix typo in dockerhub README example.
     new ede3143  NIFIREG-358 Refactoring proxy authorization to be part of Authorizables
     new 5feb697  NIFIREG-363 Adds support for Github Actions CI build on Java 8 and Java 11. Does not yet remove travis. And does not yet support the xvfb/chrome portion for jsUnitTests.
     new 2d15b7d  NIFIREG-361 - Improved handling of the /access/logout endpoint.
     new 528dcdd  NIFIREG-361 - Removed old code.
     new 1da08b1  NIFIREG-361 - Fixed javascript as per code review. Tested with ldap, still logs out user as expected.
     new 42acd04  Add prop_replace command to update nifi.registry.security.keyPasswd using either the KEY_PASSWORD or KEYSTORE_PASSWORD environment variable
     new 5843049  NIFIREG-366: updating pom parent version
     new c15ae9e  NIFIREG-348 Update NiFi logo and ico file
     new abe6554  NIFIREG-369 Set file mode to 0664 for lib directories in assembly
     new 17cecb0  NIFIREG-370 Ensuring update retrieves the latest revision from RevisionManager
     new 511b886  Fix docker maven files

The 43 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[nifi-registry] 22/43: [NIFIREG-352] update frontend deps

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 3cca3ea5452d21e12efd1efb5515fdebbdff008c
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Thu Jan 2 20:17:54 2020 -0500

    [NIFIREG-352] update frontend deps
---
 .../src/main/package-lock.json                     | 780 +++++++++++++++++----
 .../nifi-registry-web-ui/src/main/package.json     |   4 +-
 2 files changed, 639 insertions(+), 145 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
index f10fe73..ada8c0a 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
@@ -1579,6 +1579,33 @@
             "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
             "dev": true
         },
+        "agent-base": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+            "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+            "dev": true,
+            "requires": {
+                "es6-promisify": "^5.0.0"
+            }
+        },
+        "aggregate-error": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz",
+            "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==",
+            "dev": true,
+            "requires": {
+                "clean-stack": "^2.0.0",
+                "indent-string": "^4.0.0"
+            },
+            "dependencies": {
+                "indent-string": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+                    "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+                    "dev": true
+                }
+            }
+        },
         "ajv": {
             "version": "5.5.2",
             "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
@@ -2713,53 +2740,68 @@
             "dev": true
         },
         "cacache": {
-            "version": "11.3.2",
-            "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz",
-            "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==",
+            "version": "13.0.1",
+            "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz",
+            "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==",
             "dev": true,
             "requires": {
-                "bluebird": "^3.5.3",
-                "chownr": "^1.1.1",
+                "chownr": "^1.1.2",
                 "figgy-pudding": "^3.5.1",
-                "glob": "^7.1.3",
-                "graceful-fs": "^4.1.15",
+                "fs-minipass": "^2.0.0",
+                "glob": "^7.1.4",
+                "graceful-fs": "^4.2.2",
+                "infer-owner": "^1.0.4",
                 "lru-cache": "^5.1.1",
-                "mississippi": "^3.0.0",
+                "minipass": "^3.0.0",
+                "minipass-collect": "^1.0.2",
+                "minipass-flush": "^1.0.5",
+                "minipass-pipeline": "^1.2.2",
                 "mkdirp": "^0.5.1",
                 "move-concurrently": "^1.0.1",
+                "p-map": "^3.0.0",
                 "promise-inflight": "^1.0.1",
-                "rimraf": "^2.6.2",
-                "ssri": "^6.0.1",
-                "unique-filename": "^1.1.1",
-                "y18n": "^4.0.0"
+                "rimraf": "^2.7.1",
+                "ssri": "^7.0.0",
+                "unique-filename": "^1.1.1"
             },
             "dependencies": {
-                "bluebird": {
-                    "version": "3.5.4",
-                    "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz",
-                    "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==",
-                    "dev": true
+                "glob": {
+                    "version": "7.1.6",
+                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+                    "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+                    "dev": true,
+                    "requires": {
+                        "fs.realpath": "^1.0.0",
+                        "inflight": "^1.0.4",
+                        "inherits": "2",
+                        "minimatch": "^3.0.4",
+                        "once": "^1.3.0",
+                        "path-is-absolute": "^1.0.0"
+                    }
                 },
-                "chownr": {
-                    "version": "1.1.1",
-                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
-                    "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
+                "graceful-fs": {
+                    "version": "4.2.3",
+                    "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
+                    "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
                     "dev": true
                 },
+                "p-map": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+                    "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
+                    "dev": true,
+                    "requires": {
+                        "aggregate-error": "^3.0.0"
+                    }
+                },
                 "rimraf": {
-                    "version": "2.6.3",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-                    "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
                     "dev": true,
                     "requires": {
                         "glob": "^7.1.3"
                     }
-                },
-                "y18n": {
-                    "version": "4.0.0",
-                    "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
-                    "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
-                    "dev": true
                 }
             }
         },
@@ -3000,6 +3042,12 @@
                 }
             }
         },
+        "chownr": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
+            "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==",
+            "dev": true
+        },
         "chrome-trace-event": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz",
@@ -3079,6 +3127,12 @@
                 }
             }
         },
+        "clean-stack": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+            "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+            "dev": true
+        },
         "cli-cursor": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
@@ -3369,17 +3423,143 @@
             }
         },
         "compression-webpack-plugin": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-2.0.0.tgz",
-            "integrity": "sha512-bDgd7oTUZC8EkRx8j0sjyCfeiO+e5sFcfgaFcjVhfQf5lLya7oY2BczxcJ7IUuVjz5m6fy8IECFmVFew3xLk8Q==",
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-3.0.1.tgz",
+            "integrity": "sha512-FOwoBVzDiwSdJDnZTKXDpAjJU90k8SbChgxnoiYwTo15xjIDJkSC8wFKuc13DymXjgasPEqzS5+2RUgSKXdKKA==",
             "dev": true,
             "requires": {
-                "cacache": "^11.2.0",
-                "find-cache-dir": "^2.0.0",
+                "cacache": "^13.0.1",
+                "find-cache-dir": "^3.0.0",
                 "neo-async": "^2.5.0",
-                "schema-utils": "^1.0.0",
-                "serialize-javascript": "^1.4.0",
+                "schema-utils": "^2.6.1",
+                "serialize-javascript": "^2.1.2",
                 "webpack-sources": "^1.0.1"
+            },
+            "dependencies": {
+                "ajv": {
+                    "version": "6.10.2",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+                    "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+                    "dev": true,
+                    "requires": {
+                        "fast-deep-equal": "^2.0.1",
+                        "fast-json-stable-stringify": "^2.0.0",
+                        "json-schema-traverse": "^0.4.1",
+                        "uri-js": "^4.2.2"
+                    }
+                },
+                "ajv-keywords": {
+                    "version": "3.4.1",
+                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+                    "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+                    "dev": true
+                },
+                "fast-deep-equal": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+                    "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+                    "dev": true
+                },
+                "find-cache-dir": {
+                    "version": "3.2.0",
+                    "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz",
+                    "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==",
+                    "dev": true,
+                    "requires": {
+                        "commondir": "^1.0.1",
+                        "make-dir": "^3.0.0",
+                        "pkg-dir": "^4.1.0"
+                    }
+                },
+                "find-up": {
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+                    "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^5.0.0",
+                        "path-exists": "^4.0.0"
+                    }
+                },
+                "json-schema-traverse": {
+                    "version": "0.4.1",
+                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+                    "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+                    "dev": true
+                },
+                "locate-path": {
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+                    "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+                    "dev": true,
+                    "requires": {
+                        "p-locate": "^4.1.0"
+                    }
+                },
+                "make-dir": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz",
+                    "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==",
+                    "dev": true,
+                    "requires": {
+                        "semver": "^6.0.0"
+                    }
+                },
+                "p-limit": {
+                    "version": "2.2.2",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+                    "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+                    "dev": true,
+                    "requires": {
+                        "p-try": "^2.0.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+                    "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+                    "dev": true,
+                    "requires": {
+                        "p-limit": "^2.2.0"
+                    }
+                },
+                "p-try": {
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+                    "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+                    "dev": true
+                },
+                "path-exists": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+                    "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+                    "dev": true
+                },
+                "pkg-dir": {
+                    "version": "4.2.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+                    "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^4.0.0"
+                    }
+                },
+                "schema-utils": {
+                    "version": "2.6.1",
+                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.1.tgz",
+                    "integrity": "sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg==",
+                    "dev": true,
+                    "requires": {
+                        "ajv": "^6.10.2",
+                        "ajv-keywords": "^3.4.1"
+                    }
+                },
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+                    "dev": true
+                }
             }
         },
         "concat-map": {
@@ -3512,9 +3692,9 @@
             },
             "dependencies": {
                 "rimraf": {
-                    "version": "2.6.3",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-                    "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
                     "dev": true,
                     "requires": {
                         "glob": "^7.1.3"
@@ -3912,9 +4092,9 @@
             "dev": true
         },
         "cyclist": {
-            "version": "0.2.2",
-            "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
-            "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
+            "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=",
             "dev": true
         },
         "damerau-levenshtein": {
@@ -4537,9 +4717,9 @@
             }
         },
         "es6-promise": {
-            "version": "4.2.4",
-            "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
-            "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
+            "version": "4.2.8",
+            "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+            "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
             "dev": true
         },
         "es6-promisify": {
@@ -5846,6 +6026,15 @@
                 "universalify": "^0.1.0"
             }
         },
+        "fs-minipass": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.0.0.tgz",
+            "integrity": "sha512-40Qz+LFXmd9tzYVnnBmZvFfvAADfUA14TXPK1s7IfElJTIZ97rA8w4Kin7Wt5JBrC3ShnnFJO/5vPjPEeJIq9A==",
+            "dev": true,
+            "requires": {
+                "minipass": "^3.0.0"
+            }
+        },
         "fs-write-stream-atomic": {
             "version": "1.0.10",
             "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
@@ -6871,9 +7060,9 @@
             "dev": true
         },
         "handlebars": {
-            "version": "4.4.3",
-            "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.3.tgz",
-            "integrity": "sha512-B0W4A2U1ww3q7VVthTKfh+epHx+q4mCt6iK+zEAzbMBpWQAwxCeKxEGpj/1oQTpzPXDNSOG7hmG14TsISH50yw==",
+            "version": "4.5.3",
+            "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+            "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
             "dev": true,
             "requires": {
                 "neo-async": "^2.6.0",
@@ -7346,24 +7535,13 @@
             "dev": true
         },
         "https-proxy-agent": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
-            "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+            "version": "2.2.4",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz",
+            "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==",
             "dev": true,
             "requires": {
-                "agent-base": "^4.1.0",
+                "agent-base": "^4.3.0",
                 "debug": "^3.1.0"
-            },
-            "dependencies": {
-                "agent-base": {
-                    "version": "4.2.1",
-                    "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
-                    "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
-                    "dev": true,
-                    "requires": {
-                        "es6-promisify": "^5.0.0"
-                    }
-                }
             }
         },
         "husky": {
@@ -7643,6 +7821,12 @@
             "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
             "dev": true
         },
+        "infer-owner": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+            "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+            "dev": true
+        },
         "inflight": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@@ -8582,9 +8766,9 @@
             },
             "dependencies": {
                 "handlebars": {
-                    "version": "4.4.3",
-                    "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.3.tgz",
-                    "integrity": "sha512-B0W4A2U1ww3q7VVthTKfh+epHx+q4mCt6iK+zEAzbMBpWQAwxCeKxEGpj/1oQTpzPXDNSOG7hmG14TsISH50yw==",
+                    "version": "4.5.3",
+                    "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+                    "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
                     "dev": true,
                     "requires": {
                         "neo-async": "^2.6.0",
@@ -8655,6 +8839,33 @@
             "integrity": "sha1-43zwsX8ZnM4jvqcbIDk5Uka07E4=",
             "dev": true
         },
+        "jest-worker": {
+            "version": "24.9.0",
+            "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz",
+            "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==",
+            "dev": true,
+            "requires": {
+                "merge-stream": "^2.0.0",
+                "supports-color": "^6.1.0"
+            },
+            "dependencies": {
+                "has-flag": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+                    "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+                    "dev": true
+                },
+                "supports-color": {
+                    "version": "6.1.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+                    "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
+                    "dev": true,
+                    "requires": {
+                        "has-flag": "^3.0.0"
+                    }
+                }
+            }
+        },
         "jquery": {
             "version": "3.4.1",
             "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
@@ -9718,9 +9929,9 @@
             },
             "dependencies": {
                 "yallist": {
-                    "version": "3.0.3",
-                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
-                    "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==",
+                    "version": "3.1.1",
+                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+                    "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
                     "dev": true
                 }
             }
@@ -9910,6 +10121,12 @@
             "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
             "dev": true
         },
+        "merge-stream": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+            "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+            "dev": true
+        },
         "merge2": {
             "version": "1.2.3",
             "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz",
@@ -10039,36 +10256,50 @@
                 "is-plain-obj": "^1.1.0"
             }
         },
-        "mississippi": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
-            "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+        "minipass": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.1.tgz",
+            "integrity": "sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==",
             "dev": true,
             "requires": {
-                "concat-stream": "^1.5.0",
-                "duplexify": "^3.4.2",
-                "end-of-stream": "^1.1.0",
-                "flush-write-stream": "^1.0.0",
-                "from2": "^2.1.0",
-                "parallel-transform": "^1.1.0",
-                "pump": "^3.0.0",
-                "pumpify": "^1.3.3",
-                "stream-each": "^1.1.0",
-                "through2": "^2.0.0"
+                "yallist": "^4.0.0"
             },
             "dependencies": {
-                "pump": {
-                    "version": "3.0.0",
-                    "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
-                    "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
-                    "dev": true,
-                    "requires": {
-                        "end-of-stream": "^1.1.0",
-                        "once": "^1.3.1"
-                    }
+                "yallist": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+                    "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+                    "dev": true
                 }
             }
         },
+        "minipass-collect": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+            "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+            "dev": true,
+            "requires": {
+                "minipass": "^3.0.0"
+            }
+        },
+        "minipass-flush": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+            "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+            "dev": true,
+            "requires": {
+                "minipass": "^3.0.0"
+            }
+        },
+        "minipass-pipeline": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz",
+            "integrity": "sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA==",
+            "dev": true,
+            "requires": {
+                "minipass": "^3.0.0"
+            }
+        },
         "mixin-deep": {
             "version": "1.3.2",
             "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
@@ -10137,9 +10368,9 @@
             },
             "dependencies": {
                 "rimraf": {
-                    "version": "2.6.3",
-                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
-                    "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
                     "dev": true,
                     "requires": {
                         "glob": "^7.1.3"
@@ -10847,12 +11078,12 @@
             "dev": true
         },
         "parallel-transform": {
-            "version": "1.1.0",
-            "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz",
-            "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
+            "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
             "dev": true,
             "requires": {
-                "cyclist": "~0.2.2",
+                "cyclist": "^1.0.1",
                 "inherits": "^2.0.3",
                 "readable-stream": "^2.1.5"
             }
@@ -12025,9 +12256,9 @@
             }
         },
         "pump": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
-            "integrity": "sha1-Ejma3W5M91Jtlzy8i1zi4pCLOQk=",
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+            "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
             "dev": true,
             "requires": {
                 "end-of-stream": "^1.1.0",
@@ -12043,6 +12274,18 @@
                 "duplexify": "^3.6.0",
                 "inherits": "^2.0.3",
                 "pump": "^2.0.0"
+            },
+            "dependencies": {
+                "pump": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
+                    "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
+                    "dev": true,
+                    "requires": {
+                        "end-of-stream": "^1.1.0",
+                        "once": "^1.3.1"
+                    }
+                }
             }
         },
         "punycode": {
@@ -12985,9 +13228,9 @@
             }
         },
         "serialize-javascript": {
-            "version": "1.7.0",
-            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz",
-            "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==",
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
+            "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
             "dev": true
         },
         "serve-index": {
@@ -13632,12 +13875,13 @@
             }
         },
         "ssri": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
-            "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz",
+            "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==",
             "dev": true,
             "requires": {
-                "figgy-pudding": "^3.5.1"
+                "figgy-pudding": "^3.5.1",
+                "minipass": "^3.1.1"
             }
         },
         "stable": {
@@ -13728,9 +13972,9 @@
             }
         },
         "stream-shift": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
-            "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
+            "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
             "dev": true
         },
         "streamroller": {
@@ -14547,14 +14791,14 @@
             }
         },
         "terser": {
-            "version": "3.17.0",
-            "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
-            "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==",
+            "version": "4.5.1",
+            "resolved": "https://registry.npmjs.org/terser/-/terser-4.5.1.tgz",
+            "integrity": "sha512-lH9zLIbX8PRBEFCTvfHGCy0s9HEKnNso1Dx9swSopF3VUnFLB8DpQ61tHxoofovNC/sG0spajJM3EIIRSTByiQ==",
             "dev": true,
             "requires": {
-                "commander": "^2.19.0",
+                "commander": "^2.20.0",
                 "source-map": "~0.6.1",
-                "source-map-support": "~0.5.10"
+                "source-map-support": "~0.5.12"
             },
             "dependencies": {
                 "source-map": {
@@ -14564,9 +14808,9 @@
                     "dev": true
                 },
                 "source-map-support": {
-                    "version": "0.5.12",
-                    "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz",
-                    "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==",
+                    "version": "0.5.16",
+                    "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
+                    "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
                     "dev": true,
                     "requires": {
                         "buffer-from": "^1.0.0",
@@ -14576,26 +14820,160 @@
             }
         },
         "terser-webpack-plugin": {
-            "version": "1.2.3",
-            "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz",
-            "integrity": "sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA==",
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.1.tgz",
+            "integrity": "sha512-dNxivOXmDgZqrGxOttBH6B4xaxT4zNC+Xd+2K8jwGDMK5q2CZI+KZMA1AAnSRT+BTRvuzKsDx+fpxzPAmAMVcA==",
             "dev": true,
             "requires": {
-                "cacache": "^11.0.2",
-                "find-cache-dir": "^2.0.0",
-                "schema-utils": "^1.0.0",
-                "serialize-javascript": "^1.4.0",
+                "cacache": "^13.0.1",
+                "find-cache-dir": "^3.2.0",
+                "jest-worker": "^24.9.0",
+                "schema-utils": "^2.6.1",
+                "serialize-javascript": "^2.1.2",
                 "source-map": "^0.6.1",
-                "terser": "^3.16.1",
-                "webpack-sources": "^1.1.0",
-                "worker-farm": "^1.5.2"
+                "terser": "^4.4.3",
+                "webpack-sources": "^1.4.3"
             },
             "dependencies": {
+                "ajv": {
+                    "version": "6.10.2",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
+                    "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
+                    "dev": true,
+                    "requires": {
+                        "fast-deep-equal": "^2.0.1",
+                        "fast-json-stable-stringify": "^2.0.0",
+                        "json-schema-traverse": "^0.4.1",
+                        "uri-js": "^4.2.2"
+                    }
+                },
+                "ajv-keywords": {
+                    "version": "3.4.1",
+                    "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
+                    "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==",
+                    "dev": true
+                },
+                "fast-deep-equal": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+                    "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+                    "dev": true
+                },
+                "find-cache-dir": {
+                    "version": "3.2.0",
+                    "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.2.0.tgz",
+                    "integrity": "sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg==",
+                    "dev": true,
+                    "requires": {
+                        "commondir": "^1.0.1",
+                        "make-dir": "^3.0.0",
+                        "pkg-dir": "^4.1.0"
+                    }
+                },
+                "find-up": {
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+                    "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^5.0.0",
+                        "path-exists": "^4.0.0"
+                    }
+                },
+                "json-schema-traverse": {
+                    "version": "0.4.1",
+                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+                    "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+                    "dev": true
+                },
+                "locate-path": {
+                    "version": "5.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+                    "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+                    "dev": true,
+                    "requires": {
+                        "p-locate": "^4.1.0"
+                    }
+                },
+                "make-dir": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz",
+                    "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==",
+                    "dev": true,
+                    "requires": {
+                        "semver": "^6.0.0"
+                    }
+                },
+                "p-limit": {
+                    "version": "2.2.2",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz",
+                    "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==",
+                    "dev": true,
+                    "requires": {
+                        "p-try": "^2.0.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "4.1.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+                    "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+                    "dev": true,
+                    "requires": {
+                        "p-limit": "^2.2.0"
+                    }
+                },
+                "p-try": {
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+                    "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+                    "dev": true
+                },
+                "path-exists": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+                    "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+                    "dev": true
+                },
+                "pkg-dir": {
+                    "version": "4.2.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+                    "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^4.0.0"
+                    }
+                },
+                "schema-utils": {
+                    "version": "2.6.1",
+                    "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.1.tgz",
+                    "integrity": "sha512-0WXHDs1VDJyo+Zqs9TKLKyD/h7yDpHUhEFsM2CzkICFdoX1av+GBq/J2xRTFfsQO5kBfhZzANf2VcIm84jqDbg==",
+                    "dev": true,
+                    "requires": {
+                        "ajv": "^6.10.2",
+                        "ajv-keywords": "^3.4.1"
+                    }
+                },
+                "semver": {
+                    "version": "6.3.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+                    "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+                    "dev": true
+                },
                 "source-map": {
                     "version": "0.6.1",
                     "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
                     "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
                     "dev": true
+                },
+                "webpack-sources": {
+                    "version": "1.4.3",
+                    "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+                    "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+                    "dev": true,
+                    "requires": {
+                        "source-list-map": "^2.0.0",
+                        "source-map": "~0.6.1"
+                    }
                 }
             }
         },
@@ -15149,9 +15527,9 @@
             }
         },
         "unique-slug": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.1.tgz",
-            "integrity": "sha512-n9cU6+gITaVu7VGj1Z8feKMmfAjEAQGhwD9fE3zvpRRa0wEIx8ODYkVGfSc94M2OX00tUFV8wH3zYbm1I8mxFg==",
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+            "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
             "dev": true,
             "requires": {
                 "imurmurhash": "^0.1.4"
@@ -15589,17 +15967,142 @@
                         "uri-js": "^4.2.2"
                     }
                 },
+                "cacache": {
+                    "version": "12.0.3",
+                    "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz",
+                    "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==",
+                    "dev": true,
+                    "requires": {
+                        "bluebird": "^3.5.5",
+                        "chownr": "^1.1.1",
+                        "figgy-pudding": "^3.5.1",
+                        "glob": "^7.1.4",
+                        "graceful-fs": "^4.1.15",
+                        "infer-owner": "^1.0.3",
+                        "lru-cache": "^5.1.1",
+                        "mississippi": "^3.0.0",
+                        "mkdirp": "^0.5.1",
+                        "move-concurrently": "^1.0.1",
+                        "promise-inflight": "^1.0.1",
+                        "rimraf": "^2.6.3",
+                        "ssri": "^6.0.1",
+                        "unique-filename": "^1.1.1",
+                        "y18n": "^4.0.0"
+                    },
+                    "dependencies": {
+                        "mississippi": {
+                            "version": "3.0.0",
+                            "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
+                            "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
+                            "dev": true,
+                            "requires": {
+                                "concat-stream": "^1.5.0",
+                                "duplexify": "^3.4.2",
+                                "end-of-stream": "^1.1.0",
+                                "flush-write-stream": "^1.0.0",
+                                "from2": "^2.1.0",
+                                "parallel-transform": "^1.1.0",
+                                "pump": "^3.0.0",
+                                "pumpify": "^1.3.3",
+                                "stream-each": "^1.1.0",
+                                "through2": "^2.0.0"
+                            }
+                        }
+                    }
+                },
                 "fast-deep-equal": {
                     "version": "2.0.1",
                     "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
                     "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
                     "dev": true
                 },
+                "glob": {
+                    "version": "7.1.6",
+                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+                    "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+                    "dev": true,
+                    "requires": {
+                        "fs.realpath": "^1.0.0",
+                        "inflight": "^1.0.4",
+                        "inherits": "2",
+                        "minimatch": "^3.0.4",
+                        "once": "^1.3.0",
+                        "path-is-absolute": "^1.0.0"
+                    }
+                },
                 "json-schema-traverse": {
                     "version": "0.4.1",
                     "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
                     "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
                     "dev": true
+                },
+                "rimraf": {
+                    "version": "2.7.1",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+                    "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+                    "dev": true,
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                },
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+                    "dev": true
+                },
+                "ssri": {
+                    "version": "6.0.1",
+                    "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz",
+                    "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==",
+                    "dev": true,
+                    "requires": {
+                        "figgy-pudding": "^3.5.1"
+                    }
+                },
+                "terser-webpack-plugin": {
+                    "version": "1.4.3",
+                    "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz",
+                    "integrity": "sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA==",
+                    "dev": true,
+                    "requires": {
+                        "cacache": "^12.0.2",
+                        "find-cache-dir": "^2.1.0",
+                        "is-wsl": "^1.1.0",
+                        "schema-utils": "^1.0.0",
+                        "serialize-javascript": "^2.1.2",
+                        "source-map": "^0.6.1",
+                        "terser": "^4.1.2",
+                        "webpack-sources": "^1.4.0",
+                        "worker-farm": "^1.7.0"
+                    },
+                    "dependencies": {
+                        "webpack-sources": {
+                            "version": "1.4.3",
+                            "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
+                            "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+                            "dev": true,
+                            "requires": {
+                                "source-list-map": "^2.0.0",
+                                "source-map": "~0.6.1"
+                            }
+                        },
+                        "worker-farm": {
+                            "version": "1.7.0",
+                            "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
+                            "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
+                            "dev": true,
+                            "requires": {
+                                "errno": "~0.1.7"
+                            }
+                        }
+                    }
+                },
+                "y18n": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+                    "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+                    "dev": true
                 }
             }
         },
@@ -16320,15 +16823,6 @@
             "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
             "dev": true
         },
-        "worker-farm": {
-            "version": "1.6.0",
-            "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.6.0.tgz",
-            "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==",
-            "dev": true,
-            "requires": {
-                "errno": "~0.1.7"
-            }
-        },
         "wrap-ansi": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package.json
index d91b84c..7668849 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package.json
@@ -88,7 +88,7 @@
         "babel-plugin-istanbul": "5.1.4",
         "babel-polyfill": "6.26.0",
         "cache-loader": "3.0.0",
-        "compression-webpack-plugin": "2.0.0",
+        "compression-webpack-plugin": "3.0.1",
         "css-loader": "2.1.1",
         "dtsgenerator": "2.0.6",
         "eslint": "5.14.1",
@@ -122,7 +122,7 @@
         "style-loader": "0.23.1",
         "stylelint": "9.10.1",
         "stylelint-config-standard": "18.2.0",
-        "terser-webpack-plugin": "1.2.3",
+        "terser-webpack-plugin": "2.3.1",
         "ts-loader": "5.4.4",
         "typescript": "3.3.4000",
         "url-loader": "1.1.2",


[nifi-registry] 39/43: NIFIREG-366: updating pom parent version

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 584304958d90080dfecbdd1eeb4059c3c513c8e6
Author: Endre Zoltan Kovacs <an...@protonmail.com>
AuthorDate: Tue Mar 3 16:17:00 2020 +0100

    NIFIREG-366: updating pom parent version
    
    Signed-off-by: Pierre Villard <pi...@gmail.com>
    
    This closes #263.
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index d6c5161..89790c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.apache</groupId>
         <artifactId>apache</artifactId>
-        <version>17</version>
+        <version>23</version>
         <relativePath />
     </parent>
     <groupId>org.apache.nifi.registry</groupId>


[nifi-registry] 27/43: NIFIREG-356 Fixing additional classpath resources for Authorizers and ensuring proper context ClassLoader is set

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 7bbe1fa8382b2f921e7a4d2b394943a36dc1a2ab
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Fri Jan 31 13:29:55 2020 -0500

    NIFIREG-356 Fixing additional classpath resources for Authorizers and ensuring proper context ClassLoader is set
    
    This closes #256
---
 .../registry/extension/ExtensionClassLoader.java   |  37 +++++
 .../registry/extension/ExtensionCloseable.java     |   7 +
 .../nifi/registry/extension/ExtensionManager.java  |  19 +--
 .../security/authorization/AuthorizerFactory.java  | 152 ++++++++++++++-------
 .../registry/security/util/ClassLoaderUtils.java   | 138 +++++++++++++++++++
 .../authorization/AuthorizerFactorySpec.groovy     |   3 +-
 .../provider/TestStandardProviderFactory.java      |  14 +-
 .../provider/hook/TestScriptEventHookProvider.java |   6 +-
 8 files changed, 305 insertions(+), 71 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionClassLoader.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionClassLoader.java
new file mode 100644
index 0000000..1411f29
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionClassLoader.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.extension;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/**
+ * Extend URLClassLoader to keep track of the root directory.
+ */
+public class ExtensionClassLoader extends URLClassLoader {
+
+    private final String rootDir;
+
+    public ExtensionClassLoader(final String rootDir, final URL[] urls, final ClassLoader parent) {
+        super(urls, parent);
+        this.rootDir = rootDir;
+    }
+
+    public String getRootDir() {
+        return rootDir;
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java
index b24f950..0735f2c 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java
@@ -40,6 +40,13 @@ public class ExtensionCloseable implements Closeable {
         return closeable;
     }
 
+    public static ExtensionCloseable withClassLoader(final ClassLoader componentClassLoader) {
+        final ClassLoader current = Thread.currentThread().getContextClassLoader();
+        final ExtensionCloseable closeable = new ExtensionCloseable(current);
+        Thread.currentThread().setContextClassLoader(componentClassLoader);
+        return closeable;
+    }
+
     @Override
     public void close() throws IOException {
         if (toSet != null) {
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java
index 455c833..edb3350 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java
@@ -33,7 +33,6 @@ import javax.annotation.PostConstruct;
 import java.io.File;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -88,7 +87,7 @@ public class ExtensionManager {
         }
     }
 
-    public ClassLoader getExtensionClassLoader(final String canonicalClassName) {
+    public ExtensionClassLoader getExtensionClassLoader(final String canonicalClassName) {
         if (StringUtils.isBlank(canonicalClassName)) {
             throw new IllegalArgumentException("Class name can not be null");
         }
@@ -199,20 +198,4 @@ public class ExtensionManager {
         return new ExtensionClassLoader(dir, urls, parentClassLoader);
     }
 
-    /**
-     * Extend URLClassLoader to keep track of the root directory.
-     */
-    private static class ExtensionClassLoader extends URLClassLoader {
-
-        private final String rootDir;
-
-        public ExtensionClassLoader(final String rootDir, final URL[] urls, final ClassLoader parent) {
-            super(urls, parent);
-            this.rootDir = rootDir;
-        }
-
-        public String getRootDir() {
-            return rootDir;
-        }
-    }
 }
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
index a819e97..959e29e 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.registry.security.authorization;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.extension.ExtensionClassLoader;
 import org.apache.nifi.registry.extension.ExtensionCloseable;
 import org.apache.nifi.registry.extension.ExtensionManager;
 import org.apache.nifi.registry.properties.NiFiRegistryProperties;
@@ -30,6 +31,7 @@ import org.apache.nifi.registry.security.authorization.generated.Authorizers;
 import org.apache.nifi.registry.security.authorization.generated.Prop;
 import org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
 import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
+import org.apache.nifi.registry.security.util.ClassLoaderUtils;
 import org.apache.nifi.registry.security.util.XmlUtils;
 import org.apache.nifi.registry.service.RegistryService;
 import org.slf4j.Logger;
@@ -55,7 +57,11 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -201,11 +207,12 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
 
                         // configure each authorizer
                         for (final org.apache.nifi.registry.security.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) {
+                            if (provider.getIdentifier().equals(authorizerIdentifier)) {
+                                continue;
+                            }
                             final Authorizer instance = authorizers.get(provider.getIdentifier());
-                            final Class authorizerClass = instance instanceof WrappedAuthorizer
-                                    ? ((WrappedAuthorizer) instance).getBaseAuthorizer().getClass()
-                                    : instance.getClass();
-                            try (ExtensionCloseable extCloseable = ExtensionCloseable.withComponentClassLoader(extensionManager, authorizerClass)) {
+                            final ClassLoader instanceClassLoader = instance.getClass().getClassLoader();
+                            try (final ExtensionCloseable extClosable = ExtensionCloseable.withClassLoader(instanceClassLoader)) {
                                 instance.onConfigured(loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty()));
                             }
                         }
@@ -216,7 +223,37 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
                         // ensure it was found
                         if (authorizer == null) {
                             throw new AuthorizerFactoryException(String.format("The specified authorizer '%s' could not be found.", authorizerIdentifier));
+                        } else {
+                            // get the ClassLoader of the Authorizer before wrapping it with anything
+                            final ClassLoader authorizerClassLoader = authorizer.getClass().getClassLoader();
+
+                            // install integrity checks
+                            authorizer = AuthorizerFactory.installIntegrityChecks(authorizer);
+
+                            // load the configuration context for the selected authorizer
+                            AuthorizerConfigurationContext authorizerConfigurationContext = null;
+                            for (final org.apache.nifi.registry.security.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) {
+                                if (provider.getIdentifier().equals(authorizerIdentifier)) {
+                                    authorizerConfigurationContext = loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty());
+                                    break;
+                                }
+                            }
+
+                            if (authorizerConfigurationContext == null) {
+                                throw new IllegalStateException("Unable to load configuration for authorizer with id: " + authorizerIdentifier);
+                            }
+
+                            // configure the authorizer that is wrapped with integrity checks
+                            // set the context ClassLoader the wrapped authorizer's ClassLoader
+                            try (final ExtensionCloseable extClosable = ExtensionCloseable.withClassLoader(authorizerClassLoader)) {
+                                authorizer.onConfigured(authorizerConfigurationContext);
+                            }
+
+                            // wrap the integrity checked Authorizer with the FrameworkAuthorizer
+                            authorizer = createFrameworkAuthorizer(authorizer);
                         }
+
+
                     } catch (AuthorizerFactoryException e) {
                         throw e;
                     } catch (Exception e) {
@@ -281,7 +318,6 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
     }
 
     private UserGroupProvider createUserGroupProvider(final String identifier, final String userGroupProviderClassName) throws Exception {
-
         final UserGroupProvider instance;
 
         final ClassLoader classLoader = extensionManager.getExtensionClassLoader(userGroupProviderClassName);
@@ -289,22 +325,24 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
             throw new IllegalStateException("Extension not found in any of the configured class loaders: " + userGroupProviderClassName);
         }
 
-        // attempt to load the class
-        Class<?> rawUserGroupProviderClass = Class.forName(userGroupProviderClassName, true, classLoader);
-        Class<? extends UserGroupProvider> userGroupProviderClass = rawUserGroupProviderClass.asSubclass(UserGroupProvider.class);
+        try (final ExtensionCloseable closeable = ExtensionCloseable.withClassLoader(classLoader)) {
+            // attempt to load the class
+            Class<?> rawUserGroupProviderClass = Class.forName(userGroupProviderClassName, true, classLoader);
+            Class<? extends UserGroupProvider> userGroupProviderClass = rawUserGroupProviderClass.asSubclass(UserGroupProvider.class);
 
-        // otherwise create a new instance
-        Constructor constructor = userGroupProviderClass.getConstructor();
-        instance = (UserGroupProvider) constructor.newInstance();
+            // otherwise create a new instance
+            Constructor constructor = userGroupProviderClass.getConstructor();
+            instance = (UserGroupProvider) constructor.newInstance();
 
-        // method injection
-        performMethodInjection(instance, userGroupProviderClass);
+            // method injection
+            performMethodInjection(instance, userGroupProviderClass);
 
-        // field injection
-        performFieldInjection(instance, userGroupProviderClass);
+            // field injection
+            performFieldInjection(instance, userGroupProviderClass);
 
-        // call post construction lifecycle event
-        instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));
+            // call post construction lifecycle event
+            instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));
+        }
 
         return instance;
     }
@@ -317,22 +355,24 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
             throw new IllegalStateException("Extension not found in any of the configured class loaders: " + accessPolicyProviderClassName);
         }
 
-        // attempt to load the class
-        Class<?> rawAccessPolicyProviderClass = Class.forName(accessPolicyProviderClassName, true, classLoader);
-        Class<? extends AccessPolicyProvider> accessPolicyClass = rawAccessPolicyProviderClass.asSubclass(AccessPolicyProvider.class);
+        try (final ExtensionCloseable closeable = ExtensionCloseable.withClassLoader(classLoader)) {
+            // attempt to load the class
+            Class<?> rawAccessPolicyProviderClass = Class.forName(accessPolicyProviderClassName, true, classLoader);
+            Class<? extends AccessPolicyProvider> accessPolicyClass = rawAccessPolicyProviderClass.asSubclass(AccessPolicyProvider.class);
 
-        // otherwise create a new instance
-        Constructor constructor = accessPolicyClass.getConstructor();
-        instance = (AccessPolicyProvider) constructor.newInstance();
+            // otherwise create a new instance
+            Constructor constructor = accessPolicyClass.getConstructor();
+            instance = (AccessPolicyProvider) constructor.newInstance();
 
-        // method injection
-        performMethodInjection(instance, accessPolicyClass);
+            // method injection
+            performMethodInjection(instance, accessPolicyClass);
 
-        // field injection
-        performFieldInjection(instance, accessPolicyClass);
+            // field injection
+            performFieldInjection(instance, accessPolicyClass);
 
-        // call post construction lifecycle event
-        instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));
+            // call post construction lifecycle event
+            instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));
+        }
 
         return instance;
     }
@@ -340,33 +380,51 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
     private Authorizer createAuthorizer(final String identifier, final String authorizerClassName, final String classpathResources) throws Exception {
         final Authorizer instance;
 
-        final ClassLoader classLoader = extensionManager.getExtensionClassLoader(authorizerClassName);
-        if (classLoader == null) {
+        ClassLoader classLoader;
+
+        final ExtensionClassLoader extensionClassLoader = extensionManager.getExtensionClassLoader(authorizerClassName);
+        if (extensionClassLoader == null) {
             throw new IllegalStateException("Extension not found in any of the configured class loaders: " + authorizerClassName);
         }
 
-        // attempt to load the class
-        Class<?> rawAuthorizerClass = Class.forName(authorizerClassName, true, classLoader);
-        Class<? extends Authorizer> authorizerClass = rawAuthorizerClass.asSubclass(Authorizer.class);
+        // if additional classpath resources were specified, replace with a new ClassLoader that contains
+        // the combined resources of the original ClassLoader + the additional resources
+        if (StringUtils.isNotEmpty(classpathResources)) {
+            logger.info(String.format("Replacing Authorizer ClassLoader for '%s' to include additional resources: %s", identifier, classpathResources));
+            final URL[] originalUrls = extensionClassLoader.getURLs();
+            final URL[] additionalUrls = ClassLoaderUtils.getURLsForClasspath(classpathResources, null, true);
 
-        // otherwise create a new instance
-        Constructor constructor = authorizerClass.getConstructor();
-        instance = (Authorizer) constructor.newInstance();
+            final Set<URL> combinedUrls = new HashSet<>();
+            combinedUrls.addAll(Arrays.asList(originalUrls));
+            combinedUrls.addAll(Arrays.asList(additionalUrls));
 
-        // method injection
-        performMethodInjection(instance, authorizerClass);
+            final URL[] urls = combinedUrls.toArray(new URL[combinedUrls.size()]);
+            classLoader = new URLClassLoader(urls, extensionClassLoader.getParent());
+        } else {
+            // no additional resources so just use the ExtensionClassLoader
+            classLoader = extensionClassLoader;
+        }
+
+        try (final ExtensionCloseable closeable = ExtensionCloseable.withClassLoader(classLoader)) {
+            // attempt to load the class
+            Class<?> rawAuthorizerClass = Class.forName(authorizerClassName, true, classLoader);
+            Class<? extends Authorizer> authorizerClass = rawAuthorizerClass.asSubclass(Authorizer.class);
 
-        // field injection
-        performFieldInjection(instance, authorizerClass);
+            // otherwise create a new instance
+            Constructor constructor = authorizerClass.getConstructor();
+            instance = (Authorizer) constructor.newInstance();
 
-        // call post construction lifecycle event
-        instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));
+            // method injection
+            performMethodInjection(instance, authorizerClass);
 
-        // wrap the instance Authorizer with checks to ensure integrity of data
-        final Authorizer integrityCheckAuthorizer = installIntegrityChecks(instance);
+            // field injection
+            performFieldInjection(instance, authorizerClass);
 
-        // wrap the integrity checked Authorizer with the FrameworkAuthorizer
-        return createFrameworkAuthorizer(integrityCheckAuthorizer);
+            // call post construction lifecycle event
+            instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this));
+        }
+
+        return instance;
     }
 
     private Authorizer createFrameworkAuthorizer(final Authorizer baseAuthorizer) {
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/util/ClassLoaderUtils.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/util/ClassLoaderUtils.java
new file mode 100644
index 0000000..1f05cd3
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/util/ClassLoaderUtils.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+public class ClassLoaderUtils {
+
+    static final Logger LOGGER = LoggerFactory.getLogger(ClassLoaderUtils.class);
+
+    public static ClassLoader getCustomClassLoader(String modulePath, ClassLoader parentClassLoader, FilenameFilter filenameFilter) throws MalformedURLException {
+        URL[] classpaths = getURLsForClasspath(modulePath, filenameFilter, false);
+        return createModuleClassLoader(classpaths, parentClassLoader);
+    }
+
+    /**
+     *
+     * @param modulePath a module path to get URLs from, the module path may be
+     * a comma-separated list of paths
+     * @param filenameFilter a filter to apply when a module path is a directory
+     * and performs a listing, a null filter will return all matches
+     * @param suppressExceptions indicates whether to suppress exceptions
+     * @return an array of URL instances representing all of the modules
+     * resolved from processing modulePath
+     * @throws MalformedURLException if a module path does not exist
+     */
+    public static URL[] getURLsForClasspath(String modulePath, FilenameFilter filenameFilter, boolean suppressExceptions) throws MalformedURLException {
+        return getURLsForClasspath(modulePath == null ? Collections.emptySet() : Collections.singleton(modulePath), filenameFilter, suppressExceptions);
+    }
+
+    /**
+     *
+     * @param modulePaths one or modules paths to get URLs from, each module
+     * path may be a comma-separated list of paths
+     * @param filenameFilter a filter to apply when a module path is a directory
+     * and performs a listing, a null filter will return all matches
+     * @param suppressExceptions if true then all modules will attempt to be
+     * resolved even if some throw an exception, if false the first exception
+     * will be thrown
+     * @return an array of URL instances representing all of the modules
+     * resolved from processing modulePaths
+     * @throws MalformedURLException if a module path does not exist
+     */
+    public static URL[] getURLsForClasspath(Set<String> modulePaths, FilenameFilter filenameFilter, boolean suppressExceptions) throws MalformedURLException {
+        // use LinkedHashSet to maintain the ordering that the incoming paths are processed
+        Set<String> modules = new LinkedHashSet<>();
+        if (modulePaths != null) {
+            modulePaths.stream()
+                    .flatMap(path -> Arrays.stream(path.split(",")))
+                    .filter(path -> isNotBlank(path))
+                    .map(String::trim)
+                    .forEach(m -> modules.add(m));
+        }
+        return toURLs(modules, filenameFilter, suppressExceptions);
+    }
+
+    private static boolean isNotBlank(final String value) {
+        return value != null && !value.trim().isEmpty();
+    }
+
+    protected static URL[] toURLs(Set<String> modulePaths, FilenameFilter filenameFilter, boolean suppressExceptions) throws MalformedURLException {
+        List<URL> additionalClasspath = new LinkedList<>();
+        if (modulePaths != null) {
+            for (String modulePathString : modulePaths) {
+                // If the path is already a URL, just add it (but don't check if it exists, too expensive and subject to network availability)
+                boolean isUrl = true;
+                try {
+                    additionalClasspath.add(new URL(modulePathString));
+                } catch (MalformedURLException mue) {
+                    isUrl = false;
+                }
+                if (!isUrl) {
+                    try {
+                        File modulePath = new File(modulePathString);
+
+                        if (modulePath.exists()) {
+
+                            additionalClasspath.add(modulePath.toURI().toURL());
+
+                            if (modulePath.isDirectory()) {
+                                File[] files = modulePath.listFiles(filenameFilter);
+
+                                if (files != null) {
+                                    for (File classpathResource : files) {
+                                        if (classpathResource.isDirectory()) {
+                                            LOGGER.warn("Recursive directories are not supported, skipping " + classpathResource.getAbsolutePath());
+                                        } else {
+                                            additionalClasspath.add(classpathResource.toURI().toURL());
+                                        }
+                                    }
+                                }
+                            }
+                        } else {
+                            throw new MalformedURLException("Path specified does not exist");
+                        }
+                    } catch (MalformedURLException e) {
+                        if (!suppressExceptions) {
+                            throw e;
+                        }
+                    }
+                }
+            }
+        }
+        return additionalClasspath.toArray(new URL[additionalClasspath.size()]);
+    }
+
+    protected static ClassLoader createModuleClassLoader(URL[] modules, ClassLoader parentClassLoader) {
+        return new URLClassLoader(modules, parentClassLoader);
+    }
+
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy b/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy
index 34dfe6b..bd79e55 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy
+++ b/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.registry.security.authorization
 
+import org.apache.nifi.registry.extension.ExtensionClassLoader
 import org.apache.nifi.registry.extension.ExtensionManager
 import org.apache.nifi.registry.properties.NiFiRegistryProperties
 import org.apache.nifi.registry.security.authorization.resource.ResourceFactory
@@ -32,7 +33,7 @@ class AuthorizerFactorySpec extends Specification {
 
     // runs before every feature method
     def setup() {
-        mockExtensionManager.getExtensionClassLoader(_) >> this.getClass().getClassLoader()
+        mockExtensionManager.getExtensionClassLoader(_) >> new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader())
         mockProperties.getPropertyKeys() >> new HashSet<String>() // Called by IdentityMappingUtil.getIdentityMappings()
 
         authorizerFactory = new AuthorizerFactory(mockProperties, mockExtensionManager, null, mockRegistryService)
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java
index 0d23110..7fb8dee 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java
@@ -17,6 +17,7 @@
 package org.apache.nifi.registry.provider;
 
 import org.apache.nifi.registry.extension.BundlePersistenceProvider;
+import org.apache.nifi.registry.extension.ExtensionClassLoader;
 import org.apache.nifi.registry.extension.ExtensionManager;
 import org.apache.nifi.registry.flow.FlowPersistenceProvider;
 import org.apache.nifi.registry.properties.NiFiRegistryProperties;
@@ -24,6 +25,7 @@ import org.junit.Test;
 import org.mockito.Mockito;
 
 import javax.sql.DataSource;
+import java.net.URL;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -38,7 +40,8 @@ public class TestStandardProviderFactory {
         props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-good.xml");
 
         final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class);
-        when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader());
+        when(extensionManager.getExtensionClassLoader(any(String.class)))
+                .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader()));
 
         final DataSource dataSource = Mockito.mock(DataSource.class);
 
@@ -68,7 +71,8 @@ public class TestStandardProviderFactory {
         props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-good.xml");
 
         final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class);
-        when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader());
+        when(extensionManager.getExtensionClassLoader(any(String.class)))
+                .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader()));
 
         final DataSource dataSource = Mockito.mock(DataSource.class);
 
@@ -82,7 +86,8 @@ public class TestStandardProviderFactory {
         props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-does-not-exist.xml");
 
         final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class);
-        when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader());
+        when(extensionManager.getExtensionClassLoader(any(String.class)))
+                .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader()));
 
         final DataSource dataSource = Mockito.mock(DataSource.class);
 
@@ -96,7 +101,8 @@ public class TestStandardProviderFactory {
         props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-class-not-found.xml");
 
         final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class);
-        when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader());
+        when(extensionManager.getExtensionClassLoader(any(String.class)))
+                .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader()));
 
         final DataSource dataSource = Mockito.mock(DataSource.class);
 
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java
index b7d241b..39d45ae 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java
@@ -16,6 +16,7 @@
  */
 package org.apache.nifi.registry.provider.hook;
 
+import org.apache.nifi.registry.extension.ExtensionClassLoader;
 import org.apache.nifi.registry.extension.ExtensionManager;
 import org.apache.nifi.registry.properties.NiFiRegistryProperties;
 import org.apache.nifi.registry.provider.ProviderCreationException;
@@ -26,6 +27,8 @@ import org.mockito.Mockito;
 
 import javax.sql.DataSource;
 
+import java.net.URL;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.when;
 
@@ -37,7 +40,8 @@ public class TestScriptEventHookProvider {
         props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/hook/bad-script-provider.xml");
 
         final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class);
-        when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader());
+        when(extensionManager.getExtensionClassLoader(any(String.class)))
+                .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader()));
 
         final DataSource dataSource = Mockito.mock(DataSource.class);
 


[nifi-registry] 36/43: NIFIREG-361 - Removed old code.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 528dcdd442ccad9b32da46707e42dbe43ae07ab5
Author: Nathan Gough <th...@gmail.com>
AuthorDate: Fri Feb 14 10:50:00 2020 -0500

    NIFIREG-361 - Removed old code.
---
 .../nifi-registry-web-ui/src/main/webapp/nf-registry.js     | 13 -------------
 1 file changed, 13 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
index 1bd5e28..371b2de 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
@@ -71,19 +71,6 @@ NfRegistry.prototype = {
      * Invalidate old tokens and route to login page
      */
     logout: function () {
-    /**
-        $.ajax({
-            type: 'DELETE',
-            url: '../nifi-registry-api/access/logout',
-        }).done(function () {
-            delete this.nfRegistryService.currentUser.identity;
-            delete this.nfRegistryService.currentUser.anonymous;
-            this.nfStorage.removeItem('jwt');
-            this.router.navigateByUrl('login');
-        }).fail(nfErrorHandler.handleAjaxError);
-        **/
-
-
         this.nfRegistryApi.deleteToLogout().subscribe(function () {
 
         });


[nifi-registry] 02/43: NIFIREG-293 Highlight in Getting Started guide that only process groups can be versioned

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 9f4012dcf9d36b36b2ffe6ec3c93738bc34acab0
Author: Andrew Lim <an...@gmail.com>
AuthorDate: Wed Sep 4 16:35:40 2019 -0400

    NIFIREG-293 Highlight in Getting Started guide that only process groups can be versioned
---
 .../nifi-registry-docs/src/main/asciidoc/getting-started.adoc         | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/getting-started.adoc b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/getting-started.adoc
index eb6ac06..6eb3ab3 100644
--- a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/getting-started.adoc
+++ b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/getting-started.adoc
@@ -95,7 +95,7 @@ image::local_registry.png["Local Registry Client"]
 
 
 === Start Version Control on a Process Group
-NiFi can now place a process group under version control.
+With NiFi connected to a NiFi Registry, dataflows can be version controlled on the *process group level*.
 
 Right-click on a process group and select "Version->Start version control" from the context menu:
 
@@ -160,7 +160,7 @@ In addition to this Getting Started Guide, more information about NiFi Registry
 
 - link:user-guide.html[Apache NiFi Registry User Guide] - This guide provides information on how to navigate the Registry UI and explains in detail how to manage flows/policies/special privileges and configure users/groups when the Registry is secured.
 - link:administration-guide.html[Apache NiFi Registry System Administrator's Guide] - A guide for setting up and administering Apache NiFi Registry. Topics covered include: system requirements, security configuration, user authentication, authorization, proxy configuration and details about the different system-level settings.
-- link:https://nifi.apache.org/docs/nifi-docs/html/user-guide.html[Apache NiFi User Guide^] - A fairly extensive guide that is often used more as a Reference Guide, as it provides information on each of the different components available in NiFi and explains how to use the different features provided by the application. It includes the section "Versioning a Dataflow" which covers the integration of NiFi with NiFi Registry. Topics covered include: connecting to a registry, version states, [...]
+- link:https://nifi.apache.org/docs/nifi-docs/html/user-guide.html[Apache NiFi User Guide^] - A fairly extensive guide that is often used more as a Reference Guide, as it provides information on each of the different components available in NiFi and explains how to use the different features provided by the application. It includes the section link:https://nifi.apache.org/docs/nifi-docs/html/user-guide.html#versioning_dataflow["Versioning a Dataflow"] which covers the integration of NiFi [...]
 - link:https://cwiki.apache.org/confluence/display/NIFI/Contributor+Guide[Contributor's Guide^] - A guide for explaining how to contribute work back to the Apache NiFi community so that others can make use of it.
 
 In addition to the guides provided here, you can browse the different


[nifi-registry] 30/43: update package-lock

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit b4a482b0c36ed1bd3c4df6ebde178933f60d0475
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Thu Jan 2 21:29:39 2020 -0500

    update package-lock
---
 .../src/main/package-lock.json                     | 22 +---------------------
 1 file changed, 1 insertion(+), 21 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
index fe0431f..02d2452 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
@@ -8719,27 +8719,7 @@
             "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
             "dev": true,
             "requires": {
-                "handlebars": "^4.1.0"
-            },
-            "dependencies": {
-                "handlebars": {
-                    "version": "4.5.3",
-                    "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
-                    "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
-                    "dev": true,
-                    "requires": {
-                        "neo-async": "^2.6.0",
-                        "optimist": "^0.6.1",
-                        "source-map": "^0.6.1",
-                        "uglify-js": "^3.1.4"
-                    }
-                },
-                "source-map": {
-                    "version": "0.6.1",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-                    "dev": true
-                }
+                "handlebars": "^4.1.2"
             }
         },
         "jasmine": {


[nifi-registry] 04/43: NIFIREG-317 Improve logging for errors that occur when creating providers

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 1bc729d63a8c90a80d7471111931f0cef7c0e6b2
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Wed Sep 4 14:46:42 2019 -0400

    NIFIREG-317 Improve logging for errors that occur when creating providers
---
 .../org/apache/nifi/registry/provider/StandardProviderFactory.java    | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
index c9eb9f5..3d14d67 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/StandardProviderFactory.java
@@ -121,6 +121,7 @@ public class StandardProviderFactory implements ProviderFactory, DisposableBean
                     final JAXBElement<Providers> element = unmarshaller.unmarshal(new StreamSource(providersConfigFile), Providers.class);
                     providersHolder.set(element.getValue());
                 } catch (SAXException | JAXBException e) {
+                    LOGGER.error(e.getMessage(), e);
                     throw new ProviderFactoryException("Unable to load the providers configuration file at: " + providersConfigFile.getAbsolutePath(), e);
                 }
             } else {
@@ -157,6 +158,7 @@ public class StandardProviderFactory implements ProviderFactory, DisposableBean
 
                 LOGGER.info("Instantiated FlowPersistenceProvider with class name {}", new Object[]{flowProviderClassName});
             } catch (Exception e) {
+                LOGGER.error(e.getMessage(), e);
                 throw new ProviderFactoryException("Error creating FlowPersistenceProvider with class name: " + flowProviderClassName, e);
             }
 
@@ -207,6 +209,7 @@ public class StandardProviderFactory implements ProviderFactory, DisposableBean
 
                     LOGGER.info("Instantiated EventHookProvider with class name {}", new Object[] {hookProviderClassName});
                 } catch (Exception e) {
+                    LOGGER.error(e.getMessage(), e);
                     throw new ProviderFactoryException("Error creating EventHookProvider with class name: " + hookProviderClassName, e);
                 }
 
@@ -250,6 +253,7 @@ public class StandardProviderFactory implements ProviderFactory, DisposableBean
 
                 LOGGER.info("Instantiated BundlePersistenceProvider with class name {}", new Object[] {extensionBundleProviderClassName});
             } catch (Exception e) {
+                LOGGER.error(e.getMessage(), e);
                 throw new ProviderFactoryException("Error creating BundlePersistenceProvider with class name: " + extensionBundleProviderClassName, e);
             }
 


[nifi-registry] 17/43: NIFIREG-339 Remove errors from root pom

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit ba0555f49ab7e76342e6224f74cca725bcfcd406
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Fri Oct 18 11:06:07 2019 -0400

    NIFIREG-339 Remove errors from root pom
---
 checkstyle.xml | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 pom.xml        | 82 ++++------------------------------------------------------
 2 files changed, 82 insertions(+), 77 deletions(-)

diff --git a/checkstyle.xml b/checkstyle.xml
new file mode 100644
index 0000000..80af4b7
--- /dev/null
+++ b/checkstyle.xml
@@ -0,0 +1,77 @@
+<!DOCTYPE module PUBLIC
+        "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
+        "https://checkstyle.org/dtds/configuration_1_3.dtd">
+<module name="Checker">
+    <property name="charset" value="UTF-8" />
+    <property name="severity" value="warning" />
+    <!-- Checks for whitespace -->
+    <!-- See https://checkstyle.sf.net/config_whitespace.html -->
+    <module name="FileTabCharacter">
+        <property name="eachLine" value="true" />
+    </module>
+    <module name="TreeWalker">
+        <module name="RegexpSinglelineJava">
+            <property name="format" value="\s+$" />
+            <property name="message" value="Line has trailing whitespace." />
+        </module>
+        <module name="RegexpSinglelineJava">
+            <property name="format" value="[@]see\s+[{][@]link" />
+            <property name="message" value="Javadoc @see does not need @link: pick one or the other." />
+        </module>
+        <module name="OuterTypeFilename" />
+        <module name="LineLength">
+            <!-- needs extra, because Eclipse formatter ignores the ending left
+            brace -->
+            <property name="max" value="200" />
+            <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://" />
+        </module>
+        <module name="AvoidStarImport" />
+        <module name="UnusedImports">
+            <property name="processJavadoc" value="true" />
+        </module>
+        <module name="NoLineWrap" />
+        <module name="LeftCurly" />
+        <module name="RightCurly" />
+        <module name="RightCurly">
+            <property name="option" value="alone_or_singleline" />
+            <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT, INSTANCE_INIT" />
+        </module>
+        <module name="SeparatorWrap">
+            <property name="tokens" value="DOT" />
+            <property name="option" value="nl" />
+        </module>
+        <module name="SeparatorWrap">
+            <property name="tokens" value="COMMA" />
+            <property name="option" value="EOL" />
+        </module>
+        <module name="PackageName">
+            <property name="format" value="^[a-z]+(\.[a-z][a-zA-Z0-9]*)*$" />
+        </module>
+        <module name="MethodTypeParameterName">
+            <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
+        </module>
+        <module name="MethodParamPad" />
+        <module name="OperatorWrap">
+            <property name="option" value="NL" />
+            <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, QUESTION, SL, SR, STAR " />
+        </module>
+        <module name="AnnotationLocation">
+            <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF" />
+        </module>
+        <module name="AnnotationLocation">
+            <property name="tokens" value="VARIABLE_DEF" />
+            <property name="allowSamelineMultipleAnnotations" value="true" />
+        </module>
+        <module name="NonEmptyAtclauseDescription" />
+        <module name="JavadocMethod">
+            <property name="allowUndeclaredRTE" value="true" />
+            <property name="allowMissingJavadoc" value="true" />
+            <property name="allowMissingParamTags" value="true" />
+            <property name="allowMissingThrowsTags" value="true" />
+            <property name="allowMissingReturnTag" value="true" />
+            <property name="allowedAnnotations" value="Override,Test,BeforeClass,AfterClass,Before,After" />
+            <property name="allowThrowsTagsForSubclasses" value="true" />
+        </module>
+        <module name="SingleLineJavadoc" />
+    </module>
+</module>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index ae1bb35..c02025c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -427,7 +427,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-javadoc-plugin</artifactId>
-                    <version>2.10.1</version>
+                    <version>3.1.1</version>
                     <configuration>
                         <failOnError>false</failOnError>
                         <quiet>true</quiet>
@@ -447,6 +447,7 @@
                         <releaseProfiles>apache-release</releaseProfiles>
                         <autoVersionSubmodules>true</autoVersionSubmodules>
                         <goals>deploy</goals>
+                        <!--suppress UnresolvedMavenProperty -->
                         <tagNameFormat>@{project.artifactId}-@{project.version}</tagNameFormat>
                         <pushChanges>false</pushChanges>
                         <localCheckout>true</localCheckout>
@@ -562,82 +563,7 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-checkstyle-plugin</artifactId>
                 <configuration>
-                    <checkstyleRules>
-                        <module name="Checker">
-                            <property name="charset" value="UTF-8" />
-                            <property name="severity" value="warning" />
-                            <!-- Checks for whitespace -->
-                            <!-- See https://checkstyle.sf.net/config_whitespace.html -->
-                            <module name="FileTabCharacter">
-                                <property name="eachLine" value="true" />
-                            </module>
-                            <module name="TreeWalker">
-                                <module name="RegexpSinglelineJava">
-                                    <property name="format" value="\s+$" />
-                                    <property name="message" value="Line has trailing whitespace." />
-                                </module>
-                                <module name="RegexpSinglelineJava">
-                                    <property name="format" value="[@]see\s+[{][@]link" />
-                                    <property name="message" value="Javadoc @see does not need @link: pick one or the other." />
-                                </module>
-                                <module name="OuterTypeFilename" />
-                                <module name="LineLength">
-                                    <!-- needs extra, because Eclipse formatter ignores the ending left 
-                                    brace -->
-                                    <property name="max" value="200" />
-                                    <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://" />
-                                </module>
-                                <module name="AvoidStarImport" />
-                                <module name="UnusedImports">
-                                    <property name="processJavadoc" value="true" />
-                                </module>
-                                <module name="NoLineWrap" />
-                                <module name="LeftCurly" />
-                                <module name="RightCurly" />
-                                <module name="RightCurly">
-                                    <property name="option" value="alone_or_singleline" />
-                                    <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, STATIC_INIT, INSTANCE_INIT" />
-                                </module>
-                                <module name="SeparatorWrap">
-                                    <property name="tokens" value="DOT" />
-                                    <property name="option" value="nl" />
-                                </module>
-                                <module name="SeparatorWrap">
-                                    <property name="tokens" value="COMMA" />
-                                    <property name="option" value="EOL" />
-                                </module>
-                                <module name="PackageName">
-                                    <property name="format" value="^[a-z]+(\.[a-z][a-zA-Z0-9]*)*$" />
-                                </module>
-                                <module name="MethodTypeParameterName">
-                                    <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
-                                </module>
-                                <module name="MethodParamPad" />
-                                <module name="OperatorWrap">
-                                    <property name="option" value="NL" />
-                                    <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, QUESTION, SL, SR, STAR " />
-                                </module>
-                                <module name="AnnotationLocation">
-                                    <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF" />
-                                </module>
-                                <module name="AnnotationLocation">
-                                    <property name="tokens" value="VARIABLE_DEF" />
-                                    <property name="allowSamelineMultipleAnnotations" value="true" />
-                                </module>
-                                <module name="NonEmptyAtclauseDescription" />
-                                <module name="JavadocMethod">
-                                    <property name="allowUndeclaredRTE" value="true" />
-                                    <property name="allowMissingJavadoc" value="true" />
-                                    <property name="allowMissingParamTags" value="true" />
-                                    <property name="allowMissingThrowsTags" value="true" />
-                                    <property name="allowMissingReturnTag" value="true" />
-                                    <property name="allowedAnnotations" value="Override,Test,BeforeClass,AfterClass,Before,After" />
-                                    <property name="allowThrowsTagsForSubclasses" value="true" />
-                                </module>
-                                <module name="SingleLineJavadoc" />
-                            </module>
-                        </module>
-                    </checkstyleRules>
+                    <configLocation>checkstyle.xml</configLocation>
                     <violationSeverity>warning</violationSeverity>
                     <includeTestSourceDirectory>true</includeTestSourceDirectory>
                 </configuration>
@@ -672,6 +598,7 @@
                         </exclude> <!-- A maven-swagger-plugin input file that does not have a mechanism of including comments -->
 			            <exclude>.travis-output-filters</exclude> <!-- grep patterns to exclude from travis output -->
                         <exclude>src/test/resources/descriptors/*</exclude>
+                        <exclude>checkstyle.xml</exclude>
                     </excludes>
                 </configuration>
                 <dependencies>
@@ -767,6 +694,7 @@
                         <plugin>
                             <groupId>org.apache.maven.plugins</groupId>
                             <artifactId>maven-javadoc-plugin</artifactId>
+                            <version>3.1.1</version>
                             <configuration>
                                 <doclint>none</doclint>
                             </configuration>


[nifi-registry] 32/43: Fix typo in dockerhub README example.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 553fe651e04c968202bcf761c876444a045e09f7
Author: Alex Voitau <vo...@users.noreply.github.com>
AuthorDate: Tue Dec 3 12:43:47 2019 -0800

    Fix typo in dockerhub README example.
---
 nifi-registry-core/nifi-registry-docker/dockerhub/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/README.md b/nifi-registry-core/nifi-registry-docker/dockerhub/README.md
index 9c41024..d3489ee 100644
--- a/nifi-registry-core/nifi-registry-docker/dockerhub/README.md
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/README.md
@@ -58,7 +58,7 @@ You can also pass in environment variables to change the NiFi Registry communica
     docker run --name nifi-registry \
       -p 19090:19090 \
       -d \
-      -e NIFI_REGISTRY_WEB_HTTP_PORT='19090'
+      -e NIFI_REGISTRY_WEB_HTTP_PORT='19090' \
       apache/nifi-registry:latest
 
 For a list of the environment variables recognised in this build, look into the .sh/secure.sh and .sh/start.sh scripts


[nifi-registry] 11/43: [NIFIREG-297] Upgrade to latest LTS release of Node (and npm)

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit b2f63072cc09e407898ff20ea7d79182cbb19cbe
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Wed Oct 9 17:24:46 2019 -0400

    [NIFIREG-297] Upgrade to latest LTS release of Node (and npm)
    
    This closes #238.
---
 nifi-registry-core/nifi-registry-web-ui/pom.xml    |     2 +-
 .../src/main/package-lock.json                     | 32092 +++++++++----------
 .../nifi-registry-web-ui/src/main/package.json     |   272 +-
 3 files changed, 16171 insertions(+), 16195 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/pom.xml b/nifi-registry-core/nifi-registry-web-ui/pom.xml
index 8abbf5d..8173c81 100644
--- a/nifi-registry-core/nifi-registry-web-ui/pom.xml
+++ b/nifi-registry-core/nifi-registry-web-ui/pom.xml
@@ -235,7 +235,7 @@
                         </goals>
                         <phase>initialize</phase>
                         <configuration>
-                            <nodeVersion>v8.10.0</nodeVersion>
+                            <nodeVersion>v10.16.3</nodeVersion>
                         </configuration>
                     </execution>
                     <!--
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
index 5f9664f..f10fe73 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
@@ -1,16528 +1,16500 @@
 {
-  "//": "Licensed to the Apache Software Foundation (ASF) under one or more",
-  "//": "contributor license agreements.  See the NOTICE file distributed with",
-  "//": "this work for additional information regarding copyright ownership.",
-  "//": "The ASF licenses this file to You 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.",
-  "name": "nifi-registry",
-  "version": "0.0.5-SNAPSHOT",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "@angular/animations": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.1.1.tgz",
-      "integrity": "sha512-9P9Yyf2/IUMs0MR4CfthBaMdizbTh8dDSLJHhMw1PjxPQ3c6mn74uY46NyxcJnCxII9oA2pnnV/O+10JFUFKMw==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/cdk": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.1.0.tgz",
-      "integrity": "sha512-CKZTtLWNSSM+DmZS5IHhhh+Tb3+N3/WnINq55yQrupk0hIsfyssMTBp6GHogE9btfo9+73B5fSK+VNj6VuD/Qw==",
-      "requires": {
-        "parse5": "5.1.0",
-        "tslib": "1.8.0"
-      }
-    },
-    "@angular/common": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.1.1.tgz",
-      "integrity": "sha512-kgLtexfPhAyNFlwJHKBkpwKyt/19pfULIJWJpUahFqXdYE3LkRNMJQqgfz7DCNpAQxG7B6u4ocq1j2Hx206kxw==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/compiler": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.1.1.tgz",
-      "integrity": "sha512-wz8Mc45EGax5RKRYYqgXI8lr1d0w+f9BDbHui7b3hQtKM5Mj1QxLXiSOYX0dt3lG4VzrxpO0Xku5tS3D4T1xxQ==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/core": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.1.1.tgz",
-      "integrity": "sha512-B6x8IZeu0Qm2H13leEcNzsx0pGKHMvowziurvDnm7W97MaVrYrgbelNsnly4wNX91FzdBtSVXqbe3jijAD9kjA==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/flex-layout": {
-      "version": "8.0.0-beta.26",
-      "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-8.0.0-beta.26.tgz",
-      "integrity": "sha512-lXDLlMSNQhidW0grvisIsj/3gqLuYyN2MvABuRYybnFTc233sXGZuOAaulqq663LA0/DP/GNcz6a+A4ZAAlmPA==",
-      "requires": {
-        "tslib": "1.8.0"
-      }
-    },
-    "@angular/forms": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.1.1.tgz",
-      "integrity": "sha512-jz05UIiIY2Zz/nEveL4Pm9mVCAd5O6JwVDWTHKQ64nKYIN9Nepzgb0ASeOBEZA4qP82KTGJtUm2AN4L7fXN6Pw==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/http": {
-      "version": "8.0.0-beta.10",
-      "resolved": "https://registry.npmjs.org/@angular/http/-/http-8.0.0-beta.10.tgz",
-      "integrity": "sha512-NV2TGnrpivJvOa4/1O/GQfFocPSib4NUieh2umNpJYa2CYjyYfgWpmh+0wDqh23ThPPxRufywZQkkSeb+X9PRA==",
-      "requires": {
-        "tslib": "1.9.3"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.9.3",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
-          "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
-        }
-      }
-    },
-    "@angular/material": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/material/-/material-8.1.1.tgz",
-      "integrity": "sha512-45aaxKuLTrthzhAhG2+OY86wafuRBteZcRjDG7rKZ3Cc3KteUp5QwAi+QbhHzs4O3WXLWTAmuLYJelRqRqqw7g==",
-      "requires": {
-        "tslib": "1.8.0"
-      }
-    },
-    "@angular/platform-browser": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.1.1.tgz",
-      "integrity": "sha512-uP9UIhi9NYTEbfvNj4misBspXkItFopA2pRk083AhHEhOKs79WvMI15w5H5ziIFeH+4UiCvyKrSnPfcjP+Yrvg==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/platform-browser-dynamic": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.1.1.tgz",
-      "integrity": "sha512-yUazvP4IBNgXjbzo+NKmu7lVYrrplAN3HSkgYszXwd9uvWLtk1CtXER5hSJE5ZE3Lawoh7PU5hOfMYbqtdAbwg==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@angular/router": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.1.1.tgz",
-      "integrity": "sha512-UTL/TjokRUd3hdePBrj1ITmBGq+EcVNz3D18lFi96461ZLQeXSbbf3vjQfL6SE53E4+hfKKR7/tOqQOgb5br7A==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@babel/code-frame": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
-      "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
-      "dev": true,
-      "requires": {
-        "@babel/highlight": "7.0.0"
-      }
-    },
-    "@babel/core": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.4.tgz",
-      "integrity": "sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "7.0.0",
-        "@babel/generator": "7.4.4",
-        "@babel/helpers": "7.4.4",
-        "@babel/parser": "7.4.4",
-        "@babel/template": "7.4.4",
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4",
-        "convert-source-map": "1.5.1",
-        "debug": "4.1.1",
-        "json5": "2.1.0",
-        "lodash": "4.17.15",
-        "resolve": "1.10.1",
-        "semver": "5.7.0",
-        "source-map": "0.5.7"
-      },
-      "dependencies": {
+    "//-01": "Licensed to the Apache Software Foundation (ASF) under one or more",
+    "//-02": "contributor license agreements.  See the NOTICE file distributed with",
+    "//-03": "this work for additional information regarding copyright ownership.",
+    "//-04": "The ASF licenses this file to You under the Apache License, Version 2.0",
+    "//-05": "(the \"License\"); you may not use this file except in compliance with",
+    "//-06": "the License.  You may obtain a copy of the License at",
+    "//-07": "",
+    "//-08": "http://www.apache.org/licenses/LICENSE-2.0",
+    "//-09": "",
+    "//-10": "Unless required by applicable law or agreed to in writing, software",
+    "//-11": "distributed under the License is distributed on an \"AS IS\" BASIS,",
+    "//-12": "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
+    "//-13": "See the License for the specific language governing permissions and",
+    "//-14": "limitations under the License.",
+    "name": "nifi-registry",
+    "version": "0.0.5-SNAPSHOT",
+    "lockfileVersion": 1,
+    "requires": true,
+    "dependencies": {
+        "@angular/animations": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.1.1.tgz",
+            "integrity": "sha512-9P9Yyf2/IUMs0MR4CfthBaMdizbTh8dDSLJHhMw1PjxPQ3c6mn74uY46NyxcJnCxII9oA2pnnV/O+10JFUFKMw==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/cdk": {
+            "version": "8.1.0",
+            "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-8.1.0.tgz",
+            "integrity": "sha512-CKZTtLWNSSM+DmZS5IHhhh+Tb3+N3/WnINq55yQrupk0hIsfyssMTBp6GHogE9btfo9+73B5fSK+VNj6VuD/Qw==",
+            "requires": {
+                "parse5": "^5.0.0",
+                "tslib": "^1.7.1"
+            }
+        },
+        "@angular/common": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.1.1.tgz",
+            "integrity": "sha512-kgLtexfPhAyNFlwJHKBkpwKyt/19pfULIJWJpUahFqXdYE3LkRNMJQqgfz7DCNpAQxG7B6u4ocq1j2Hx206kxw==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/compiler": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.1.1.tgz",
+            "integrity": "sha512-wz8Mc45EGax5RKRYYqgXI8lr1d0w+f9BDbHui7b3hQtKM5Mj1QxLXiSOYX0dt3lG4VzrxpO0Xku5tS3D4T1xxQ==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/core": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.1.1.tgz",
+            "integrity": "sha512-B6x8IZeu0Qm2H13leEcNzsx0pGKHMvowziurvDnm7W97MaVrYrgbelNsnly4wNX91FzdBtSVXqbe3jijAD9kjA==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/flex-layout": {
+            "version": "8.0.0-beta.26",
+            "resolved": "https://registry.npmjs.org/@angular/flex-layout/-/flex-layout-8.0.0-beta.26.tgz",
+            "integrity": "sha512-lXDLlMSNQhidW0grvisIsj/3gqLuYyN2MvABuRYybnFTc233sXGZuOAaulqq663LA0/DP/GNcz6a+A4ZAAlmPA==",
+            "requires": {
+                "tslib": "^1.7.1"
+            }
+        },
+        "@angular/forms": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.1.1.tgz",
+            "integrity": "sha512-jz05UIiIY2Zz/nEveL4Pm9mVCAd5O6JwVDWTHKQ64nKYIN9Nepzgb0ASeOBEZA4qP82KTGJtUm2AN4L7fXN6Pw==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/http": {
+            "version": "8.0.0-beta.10",
+            "resolved": "https://registry.npmjs.org/@angular/http/-/http-8.0.0-beta.10.tgz",
+            "integrity": "sha512-NV2TGnrpivJvOa4/1O/GQfFocPSib4NUieh2umNpJYa2CYjyYfgWpmh+0wDqh23ThPPxRufywZQkkSeb+X9PRA==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.9.3",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+                    "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ=="
+                }
+            }
+        },
+        "@angular/material": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/material/-/material-8.1.1.tgz",
+            "integrity": "sha512-45aaxKuLTrthzhAhG2+OY86wafuRBteZcRjDG7rKZ3Cc3KteUp5QwAi+QbhHzs4O3WXLWTAmuLYJelRqRqqw7g==",
+            "requires": {
+                "tslib": "^1.7.1"
+            }
+        },
+        "@angular/platform-browser": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.1.1.tgz",
+            "integrity": "sha512-uP9UIhi9NYTEbfvNj4misBspXkItFopA2pRk083AhHEhOKs79WvMI15w5H5ziIFeH+4UiCvyKrSnPfcjP+Yrvg==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/platform-browser-dynamic": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.1.1.tgz",
+            "integrity": "sha512-yUazvP4IBNgXjbzo+NKmu7lVYrrplAN3HSkgYszXwd9uvWLtk1CtXER5hSJE5ZE3Lawoh7PU5hOfMYbqtdAbwg==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@angular/router": {
+            "version": "8.1.1",
+            "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.1.1.tgz",
+            "integrity": "sha512-UTL/TjokRUd3hdePBrj1ITmBGq+EcVNz3D18lFi96461ZLQeXSbbf3vjQfL6SE53E4+hfKKR7/tOqQOgb5br7A==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@babel/code-frame": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz",
+            "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==",
+            "dev": true,
+            "requires": {
+                "@babel/highlight": "^7.0.0"
+            }
+        },
+        "@babel/core": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.4.4.tgz",
+            "integrity": "sha512-lQgGX3FPRgbz2SKmhMtYgJvVzGZrmjaF4apZ2bLwofAKiSjxU0drPh4S/VasyYXwaTs+A1gvQ45BN8SQJzHsQQ==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "@babel/generator": "^7.4.4",
+                "@babel/helpers": "^7.4.4",
+                "@babel/parser": "^7.4.4",
+                "@babel/template": "^7.4.4",
+                "@babel/traverse": "^7.4.4",
+                "@babel/types": "^7.4.4",
+                "convert-source-map": "^1.1.0",
+                "debug": "^4.1.0",
+                "json5": "^2.1.0",
+                "lodash": "^4.17.11",
+                "resolve": "^1.3.2",
+                "semver": "^5.4.1",
+                "source-map": "^0.5.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
+                },
+                "json5": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
+                    "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+                    "dev": true,
+                    "requires": {
+                        "minimist": "^1.2.0"
+                    }
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "minimist": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+                    "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+                    "dev": true
+                },
+                "ms": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+                    "dev": true
+                },
+                "resolve": {
+                    "version": "1.10.1",
+                    "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz",
+                    "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==",
+                    "dev": true,
+                    "requires": {
+                        "path-parse": "^1.0.6"
+                    }
+                },
+                "semver": {
+                    "version": "5.7.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+                    "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+                    "dev": true
+                },
+                "source-map": {
+                    "version": "0.5.7",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+                    "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/generator": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz",
+            "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.4.4",
+                "jsesc": "^2.5.1",
+                "lodash": "^4.17.11",
+                "source-map": "^0.5.0",
+                "trim-right": "^1.0.1"
+            },
+            "dependencies": {
+                "jsesc": {
+                    "version": "2.5.2",
+                    "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+                    "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+                    "dev": true
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "source-map": {
+                    "version": "0.5.7",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+                    "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/helper-annotate-as-pure": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz",
+            "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-builder-binary-assignment-operator-visitor": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
+            "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-explode-assignable-expression": "^7.1.0",
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-call-delegate": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz",
+            "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-hoist-variables": "^7.4.4",
+                "@babel/traverse": "^7.4.4",
+                "@babel/types": "^7.4.4"
+            }
+        },
+        "@babel/helper-define-map": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz",
+            "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-function-name": "^7.1.0",
+                "@babel/types": "^7.4.4",
+                "lodash": "^4.17.11"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/helper-explode-assignable-expression": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz",
+            "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==",
+            "dev": true,
+            "requires": {
+                "@babel/traverse": "^7.1.0",
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-function-name": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
+            "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-get-function-arity": "^7.0.0",
+                "@babel/template": "^7.1.0",
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-get-function-arity": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
+            "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-hoist-variables": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz",
+            "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.4.4"
+            }
+        },
+        "@babel/helper-member-expression-to-functions": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz",
+            "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-module-imports": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz",
+            "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-module-transforms": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz",
+            "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-module-imports": "^7.0.0",
+                "@babel/helper-simple-access": "^7.1.0",
+                "@babel/helper-split-export-declaration": "^7.4.4",
+                "@babel/template": "^7.4.4",
+                "@babel/types": "^7.4.4",
+                "lodash": "^4.17.11"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/helper-optimise-call-expression": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz",
+            "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-plugin-utils": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
+            "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
+            "dev": true
+        },
+        "@babel/helper-regex": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz",
+            "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==",
+            "dev": true,
+            "requires": {
+                "lodash": "^4.17.11"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/helper-remap-async-to-generator": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz",
+            "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-annotate-as-pure": "^7.0.0",
+                "@babel/helper-wrap-function": "^7.1.0",
+                "@babel/template": "^7.1.0",
+                "@babel/traverse": "^7.1.0",
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-replace-supers": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz",
+            "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-member-expression-to-functions": "^7.0.0",
+                "@babel/helper-optimise-call-expression": "^7.0.0",
+                "@babel/traverse": "^7.4.4",
+                "@babel/types": "^7.4.4"
+            }
+        },
+        "@babel/helper-simple-access": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz",
+            "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==",
+            "dev": true,
+            "requires": {
+                "@babel/template": "^7.1.0",
+                "@babel/types": "^7.0.0"
+            }
+        },
+        "@babel/helper-split-export-declaration": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
+            "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
+            "dev": true,
+            "requires": {
+                "@babel/types": "^7.4.4"
+            }
+        },
+        "@babel/helper-wrap-function": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
+            "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-function-name": "^7.1.0",
+                "@babel/template": "^7.1.0",
+                "@babel/traverse": "^7.1.0",
+                "@babel/types": "^7.2.0"
+            }
+        },
+        "@babel/helpers": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz",
+            "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==",
+            "dev": true,
+            "requires": {
+                "@babel/template": "^7.4.4",
+                "@babel/traverse": "^7.4.4",
+                "@babel/types": "^7.4.4"
+            }
+        },
+        "@babel/highlight": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
+            "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
+            "dev": true,
+            "requires": {
+                "chalk": "^2.0.0",
+                "esutils": "^2.0.2",
+                "js-tokens": "^4.0.0"
+            },
+            "dependencies": {
+                "ansi-styles": {
+                    "version": "3.2.1",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+                    "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+                    "dev": true,
+                    "requires": {
+                        "color-convert": "^1.9.0"
+                    }
+                },
+                "chalk": {
+                    "version": "2.4.2",
+                    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+                    "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-styles": "^3.2.1",
+                        "escape-string-regexp": "^1.0.5",
+                        "supports-color": "^5.3.0"
+                    }
+                },
+                "has-flag": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+                    "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+                    "dev": true
+                },
+                "js-tokens": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+                    "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+                    "dev": true
+                },
+                "supports-color": {
+                    "version": "5.5.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+                    "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+                    "dev": true,
+                    "requires": {
+                        "has-flag": "^3.0.0"
+                    }
+                }
+            }
+        },
+        "@babel/parser": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz",
+            "integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==",
+            "dev": true
+        },
+        "@babel/plugin-proposal-async-generator-functions": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz",
+            "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-remap-async-to-generator": "^7.1.0",
+                "@babel/plugin-syntax-async-generators": "^7.2.0"
+            }
+        },
+        "@babel/plugin-proposal-json-strings": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
+            "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/plugin-syntax-json-strings": "^7.2.0"
+            }
+        },
+        "@babel/plugin-proposal-object-rest-spread": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz",
+            "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/plugin-syntax-object-rest-spread": "^7.2.0"
+            }
+        },
+        "@babel/plugin-proposal-optional-catch-binding": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
+            "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/plugin-syntax-optional-catch-binding": "^7.2.0"
+            }
+        },
+        "@babel/plugin-proposal-unicode-property-regex": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz",
+            "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-regex": "^7.4.4",
+                "regexpu-core": "^4.5.4"
+            }
+        },
+        "@babel/plugin-syntax-async-generators": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
+            "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-syntax-json-strings": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
+            "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-syntax-object-rest-spread": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
+            "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-syntax-optional-catch-binding": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
+            "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-arrow-functions": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
+            "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-async-to-generator": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz",
+            "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-module-imports": "^7.0.0",
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-remap-async-to-generator": "^7.1.0"
+            }
+        },
+        "@babel/plugin-transform-block-scoped-functions": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
+            "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-block-scoping": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz",
+            "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "lodash": "^4.17.11"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/plugin-transform-classes": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz",
+            "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-annotate-as-pure": "^7.0.0",
+                "@babel/helper-define-map": "^7.4.4",
+                "@babel/helper-function-name": "^7.1.0",
+                "@babel/helper-optimise-call-expression": "^7.0.0",
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-replace-supers": "^7.4.4",
+                "@babel/helper-split-export-declaration": "^7.4.4",
+                "globals": "^11.1.0"
+            },
+            "dependencies": {
+                "globals": {
+                    "version": "11.12.0",
+                    "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+                    "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/plugin-transform-computed-properties": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
+            "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-destructuring": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz",
+            "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-dotall-regex": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz",
+            "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-regex": "^7.4.4",
+                "regexpu-core": "^4.5.4"
+            }
+        },
+        "@babel/plugin-transform-duplicate-keys": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz",
+            "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-exponentiation-operator": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
+            "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-for-of": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz",
+            "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-function-name": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz",
+            "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-function-name": "^7.1.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-literals": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
+            "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-member-expression-literals": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz",
+            "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-modules-amd": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz",
+            "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-module-transforms": "^7.1.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-modules-commonjs": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz",
+            "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-module-transforms": "^7.4.4",
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-simple-access": "^7.1.0"
+            }
+        },
+        "@babel/plugin-transform-modules-systemjs": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz",
+            "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-hoist-variables": "^7.4.4",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-modules-umd": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz",
+            "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-module-transforms": "^7.1.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-named-capturing-groups-regex": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.4.tgz",
+            "integrity": "sha512-Ki+Y9nXBlKfhD+LXaRS7v95TtTGYRAf9Y1rTDiE75zf8YQz4GDaWRXosMfJBXxnk88mGFjWdCRIeqDbon7spYA==",
+            "dev": true,
+            "requires": {
+                "regexp-tree": "^0.1.0"
+            }
+        },
+        "@babel/plugin-transform-new-target": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz",
+            "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-object-super": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz",
+            "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-replace-supers": "^7.1.0"
+            }
+        },
+        "@babel/plugin-transform-parameters": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz",
+            "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-call-delegate": "^7.4.4",
+                "@babel/helper-get-function-arity": "^7.0.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-property-literals": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz",
+            "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-regenerator": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.4.tgz",
+            "integrity": "sha512-Zz3w+pX1SI0KMIiqshFZkwnVGUhDZzpX2vtPzfJBKQQq8WsP/Xy9DNdELWivxcKOCX/Pywge4SiEaPaLtoDT4g==",
+            "dev": true,
+            "requires": {
+                "regenerator-transform": "^0.13.4"
+            }
+        },
+        "@babel/plugin-transform-reserved-words": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz",
+            "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-shorthand-properties": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
+            "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-spread": {
+            "version": "7.2.2",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz",
+            "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-sticky-regex": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
+            "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-regex": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-template-literals": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz",
+            "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-annotate-as-pure": "^7.0.0",
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-typeof-symbol": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
+            "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0"
+            }
+        },
+        "@babel/plugin-transform-unicode-regex": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz",
+            "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/helper-regex": "^7.4.4",
+                "regexpu-core": "^4.5.4"
+            }
+        },
+        "@babel/preset-env": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.4.tgz",
+            "integrity": "sha512-FU1H+ACWqZZqfw1x2G1tgtSSYSfxJLkpaUQL37CenULFARDo+h4xJoVHzRoHbK+85ViLciuI7ME4WTIhFRBBlw==",
+            "dev": true,
+            "requires": {
+                "@babel/helper-module-imports": "^7.0.0",
+                "@babel/helper-plugin-utils": "^7.0.0",
+                "@babel/plugin-proposal-async-generator-functions": "^7.2.0",
+                "@babel/plugin-proposal-json-strings": "^7.2.0",
+                "@babel/plugin-proposal-object-rest-spread": "^7.4.4",
+                "@babel/plugin-proposal-optional-catch-binding": "^7.2.0",
+                "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+                "@babel/plugin-syntax-async-generators": "^7.2.0",
+                "@babel/plugin-syntax-json-strings": "^7.2.0",
+                "@babel/plugin-syntax-object-rest-spread": "^7.2.0",
+                "@babel/plugin-syntax-optional-catch-binding": "^7.2.0",
+                "@babel/plugin-transform-arrow-functions": "^7.2.0",
+                "@babel/plugin-transform-async-to-generator": "^7.4.4",
+                "@babel/plugin-transform-block-scoped-functions": "^7.2.0",
+                "@babel/plugin-transform-block-scoping": "^7.4.4",
+                "@babel/plugin-transform-classes": "^7.4.4",
+                "@babel/plugin-transform-computed-properties": "^7.2.0",
+                "@babel/plugin-transform-destructuring": "^7.4.4",
+                "@babel/plugin-transform-dotall-regex": "^7.4.4",
+                "@babel/plugin-transform-duplicate-keys": "^7.2.0",
+                "@babel/plugin-transform-exponentiation-operator": "^7.2.0",
+                "@babel/plugin-transform-for-of": "^7.4.4",
+                "@babel/plugin-transform-function-name": "^7.4.4",
+                "@babel/plugin-transform-literals": "^7.2.0",
+                "@babel/plugin-transform-member-expression-literals": "^7.2.0",
+                "@babel/plugin-transform-modules-amd": "^7.2.0",
+                "@babel/plugin-transform-modules-commonjs": "^7.4.4",
+                "@babel/plugin-transform-modules-systemjs": "^7.4.4",
+                "@babel/plugin-transform-modules-umd": "^7.2.0",
+                "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.4",
+                "@babel/plugin-transform-new-target": "^7.4.4",
+                "@babel/plugin-transform-object-super": "^7.2.0",
+                "@babel/plugin-transform-parameters": "^7.4.4",
+                "@babel/plugin-transform-property-literals": "^7.2.0",
+                "@babel/plugin-transform-regenerator": "^7.4.4",
+                "@babel/plugin-transform-reserved-words": "^7.2.0",
+                "@babel/plugin-transform-shorthand-properties": "^7.2.0",
+                "@babel/plugin-transform-spread": "^7.2.0",
+                "@babel/plugin-transform-sticky-regex": "^7.2.0",
+                "@babel/plugin-transform-template-literals": "^7.4.4",
+                "@babel/plugin-transform-typeof-symbol": "^7.2.0",
+                "@babel/plugin-transform-unicode-regex": "^7.4.4",
+                "@babel/types": "^7.4.4",
+                "browserslist": "^4.5.2",
+                "core-js-compat": "^3.0.0",
+                "invariant": "^2.2.2",
+                "js-levenshtein": "^1.1.3",
+                "semver": "^5.5.0"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "5.7.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+                    "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/runtime": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz",
+            "integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==",
+            "dev": true,
+            "requires": {
+                "regenerator-runtime": "^0.13.2"
+            },
+            "dependencies": {
+                "regenerator-runtime": {
+                    "version": "0.13.2",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
+                    "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/template": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
+            "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "@babel/parser": "^7.4.4",
+                "@babel/types": "^7.4.4"
+            }
+        },
+        "@babel/traverse": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz",
+            "integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "@babel/generator": "^7.4.4",
+                "@babel/helper-function-name": "^7.1.0",
+                "@babel/helper-split-export-declaration": "^7.4.4",
+                "@babel/parser": "^7.4.4",
+                "@babel/types": "^7.4.4",
+                "debug": "^4.1.0",
+                "globals": "^11.1.0",
+                "lodash": "^4.17.11"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
+                },
+                "globals": {
+                    "version": "11.12.0",
+                    "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+                    "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+                    "dev": true
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "ms": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+                    "dev": true
+                }
+            }
+        },
+        "@babel/types": {
+            "version": "7.4.4",
+            "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz",
+            "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==",
+            "dev": true,
+            "requires": {
+                "esutils": "^2.0.2",
+                "lodash": "^4.17.11",
+                "to-fast-properties": "^2.0.0"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "to-fast-properties": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+                    "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+                    "dev": true
+                }
+            }
+        },
+        "@covalent/core": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/@covalent/core/-/core-2.1.0.tgz",
+            "integrity": "sha512-I3/VL76E198y8O2vWXci7uLEfBEB9dO8uZWwaJN3RFlSuS/HCzc/NUrElJ9aRwgmTm8KLQgJheVbg/CRQbn2Ug==",
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.10.0",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
+                    "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
+                }
+            }
+        },
+        "@mrmlnc/readdir-enhanced": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
+            "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+            "dev": true,
+            "requires": {
+                "call-me-maybe": "^1.0.1",
+                "glob-to-regexp": "^0.3.0"
+            }
+        },
+        "@nifi-fds/core": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/@nifi-fds/core/-/core-0.2.0.tgz",
+            "integrity": "sha512-6yadtM2ahtkeFnuYN+D6M0qB81y2F3uBAC6ZovXe1c1lSocXSuJCoFJq9NRW6KFFqYAQnOyZi1+hA1Kw2+UfXg=="
+        },
+        "@nodelib/fs.stat": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
+            "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
+            "dev": true
+        },
+        "@samverschueren/stream-to-observable": {
+            "version": "0.3.0",
+            "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
+            "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==",
+            "dev": true,
+            "requires": {
+                "any-observable": "^0.3.0"
+            }
+        },
+        "@types/events": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
+            "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
+            "dev": true
+        },
+        "@types/glob": {
+            "version": "7.1.1",
+            "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
+            "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
+            "dev": true,
+            "requires": {
+                "@types/events": "*",
+                "@types/minimatch": "*",
+                "@types/node": "*"
+            }
+        },
+        "@types/minimatch": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
+            "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
+            "dev": true
+        },
+        "@types/node": {
+            "version": "6.0.106",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.106.tgz",
+            "integrity": "sha1-ORvDWYq1gjVj9xVYRyEhUok+3Nc=",
+            "dev": true
+        },
+        "@types/normalize-package-data": {
+            "version": "2.4.0",
+            "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
+            "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
+            "dev": true
+        },
+        "@types/q": {
+            "version": "0.0.32",
+            "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
+            "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
+            "dev": true
+        },
+        "@types/selenium-webdriver": {
+            "version": "3.0.10",
+            "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz",
+            "integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==",
+            "dev": true
+        },
+        "@types/source-list-map": {
+            "version": "0.1.2",
+            "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
+            "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
+            "dev": true
+        },
+        "@types/unist": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
+            "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==",
+            "dev": true
+        },
+        "@types/vfile": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz",
+            "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==",
+            "dev": true,
+            "requires": {
+                "@types/node": "*",
+                "@types/unist": "*",
+                "@types/vfile-message": "*"
+            }
+        },
+        "@types/vfile-message": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz",
+            "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==",
+            "dev": true,
+            "requires": {
+                "@types/node": "*",
+                "@types/unist": "*"
+            }
+        },
+        "@types/webpack-sources": {
+            "version": "0.1.5",
+            "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz",
+            "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==",
+            "dev": true,
+            "requires": {
+                "@types/node": "*",
+                "@types/source-list-map": "*",
+                "source-map": "^0.6.1"
+            },
+            "dependencies": {
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+                    "dev": true
+                }
+            }
+        },
+        "@typescript-eslint/eslint-plugin": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.6.0.tgz",
+            "integrity": "sha512-U224c29E2lo861TQZs6GSmyC0OYeRNg6bE9UVIiFBxN2MlA0nq2dCrgIVyyRbC05UOcrgf2Wk/CF2gGOPQKUSQ==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/parser": "1.6.0",
+                "@typescript-eslint/typescript-estree": "1.6.0",
+                "requireindex": "^1.2.0",
+                "tsutils": "^3.7.0"
+            }
+        },
+        "@typescript-eslint/parser": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.6.0.tgz",
+            "integrity": "sha512-VB9xmSbfafI+/kI4gUK3PfrkGmrJQfh0N4EScT1gZXSZyUxpsBirPL99EWZg9MmPG0pzq/gMtgkk7/rAHj4aQw==",
+            "dev": true,
+            "requires": {
+                "@typescript-eslint/typescript-estree": "1.6.0",
+                "eslint-scope": "^4.0.0",
+                "eslint-visitor-keys": "^1.0.0"
+            }
+        },
+        "@typescript-eslint/typescript-estree": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.6.0.tgz",
+            "integrity": "sha512-A4CanUwfaG4oXobD5y7EXbsOHjCwn8tj1RDd820etpPAjH+Icjc2K9e/DQM1Hac5zH2BSy+u6bjvvF2wwREvYA==",
+            "dev": true,
+            "requires": {
+                "lodash.unescape": "4.0.1",
+                "semver": "5.5.0"
+            },
+            "dependencies": {
+                "semver": {
+                    "version": "5.5.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+                    "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+                    "dev": true
+                }
+            }
+        },
+        "@webassemblyjs/ast": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
+            "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/helper-module-context": "1.8.5",
+                "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+                "@webassemblyjs/wast-parser": "1.8.5"
+            }
+        },
+        "@webassemblyjs/floating-point-hex-parser": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
+            "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==",
+            "dev": true
+        },
+        "@webassemblyjs/helper-api-error": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
+            "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==",
+            "dev": true
+        },
+        "@webassemblyjs/helper-buffer": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
+            "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==",
+            "dev": true
+        },
+        "@webassemblyjs/helper-code-frame": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
+            "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/wast-printer": "1.8.5"
+            }
+        },
+        "@webassemblyjs/helper-fsm": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
+            "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==",
+            "dev": true
+        },
+        "@webassemblyjs/helper-module-context": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
+            "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "mamacro": "^0.0.3"
+            }
+        },
+        "@webassemblyjs/helper-wasm-bytecode": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
+            "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==",
+            "dev": true
+        },
+        "@webassemblyjs/helper-wasm-section": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
+            "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/helper-buffer": "1.8.5",
+                "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+                "@webassemblyjs/wasm-gen": "1.8.5"
+            }
+        },
+        "@webassemblyjs/ieee754": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
+            "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
+            "dev": true,
+            "requires": {
+                "@xtuc/ieee754": "^1.2.0"
+            }
+        },
+        "@webassemblyjs/leb128": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
+            "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
+            "dev": true,
+            "requires": {
+                "@xtuc/long": "4.2.2"
+            }
+        },
+        "@webassemblyjs/utf8": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
+            "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==",
+            "dev": true
+        },
+        "@webassemblyjs/wasm-edit": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
+            "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/helper-buffer": "1.8.5",
+                "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+                "@webassemblyjs/helper-wasm-section": "1.8.5",
+                "@webassemblyjs/wasm-gen": "1.8.5",
+                "@webassemblyjs/wasm-opt": "1.8.5",
+                "@webassemblyjs/wasm-parser": "1.8.5",
+                "@webassemblyjs/wast-printer": "1.8.5"
+            }
+        },
+        "@webassemblyjs/wasm-gen": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
+            "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+                "@webassemblyjs/ieee754": "1.8.5",
+                "@webassemblyjs/leb128": "1.8.5",
+                "@webassemblyjs/utf8": "1.8.5"
+            }
+        },
+        "@webassemblyjs/wasm-opt": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
+            "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/helper-buffer": "1.8.5",
+                "@webassemblyjs/wasm-gen": "1.8.5",
+                "@webassemblyjs/wasm-parser": "1.8.5"
+            }
+        },
+        "@webassemblyjs/wasm-parser": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
+            "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/helper-api-error": "1.8.5",
+                "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
+                "@webassemblyjs/ieee754": "1.8.5",
+                "@webassemblyjs/leb128": "1.8.5",
+                "@webassemblyjs/utf8": "1.8.5"
+            }
+        },
+        "@webassemblyjs/wast-parser": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
+            "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/floating-point-hex-parser": "1.8.5",
+                "@webassemblyjs/helper-api-error": "1.8.5",
+                "@webassemblyjs/helper-code-frame": "1.8.5",
+                "@webassemblyjs/helper-fsm": "1.8.5",
+                "@xtuc/long": "4.2.2"
+            }
+        },
+        "@webassemblyjs/wast-printer": {
+            "version": "1.8.5",
+            "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
+            "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
+            "dev": true,
+            "requires": {
+                "@webassemblyjs/ast": "1.8.5",
+                "@webassemblyjs/wast-parser": "1.8.5",
+                "@xtuc/long": "4.2.2"
+            }
+        },
+        "@xtuc/ieee754": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+            "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
+            "dev": true
+        },
+        "@xtuc/long": {
+            "version": "4.2.2",
+            "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+            "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
+            "dev": true
+        },
+        "abbrev": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+            "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+            "dev": true
+        },
+        "accepts": {
+            "version": "1.3.5",
+            "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
+            "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
+            "dev": true,
+            "requires": {
+                "mime-types": "~2.1.18",
+                "negotiator": "0.6.1"
+            }
+        },
+        "acorn": {
+            "version": "6.1.1",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
+            "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
+            "dev": true
+        },
+        "acorn-dynamic-import": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz",
+            "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==",
+            "dev": true
+        },
+        "acorn-jsx": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
+            "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
+            "dev": true
+        },
+        "adm-zip": {
+            "version": "0.4.11",
+            "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
+            "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
+            "dev": true
+        },
+        "after": {
+            "version": "0.8.2",
+            "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
+            "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
+            "dev": true
+        },
+        "ajv": {
+            "version": "5.5.2",
+            "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+            "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
+            "dev": true,
+            "requires": {
+                "co": "^4.6.0",
+                "fast-deep-equal": "^1.0.0",
+                "fast-json-stable-stringify": "^2.0.0",
+                "json-schema-traverse": "^0.3.0"
+            }
+        },
+        "ajv-errors": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
+            "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
+            "dev": true
+        },
+        "ajv-keywords": {
+            "version": "3.4.0",
+            "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz",
+            "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==",
+            "dev": true
+        },
+        "alphanum-sort": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
+            "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
+            "dev": true
+        },
+        "amdefine": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+            "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+            "dev": true
+        },
+        "angular2-jwt": {
+            "version": "0.2.3",
+            "resolved": "https://registry.npmjs.org/angular2-jwt/-/angular2-jwt-0.2.3.tgz",
+            "integrity": "sha1-VO/do87tuoX2o3sWXyKsIrit8CE="
+        },
+        "angular2-moment": {
+            "version": "1.9.0",
+            "resolved": "https://registry.npmjs.org/angular2-moment/-/angular2-moment-1.9.0.tgz",
+            "integrity": "sha512-ybPjYizpKVWAI2Z4AqxAS6s3FMkF3+zRpfvxX1wIdSJUFjl83XxQ5f2yn7retX68NSYZZ/JTK9KGnvOzZfrIZw==",
+            "requires": {
+                "moment": "^2.19.3"
+            }
+        },
+        "ansi-colors": {
+            "version": "3.2.4",
+            "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
+            "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
+            "dev": true
+        },
+        "ansi-escapes": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+            "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
+            "dev": true
+        },
+        "ansi-html": {
+            "version": "0.0.7",
+            "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
+            "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
+            "dev": true
+        },
+        "ansi-regex": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+            "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+            "dev": true
+        },
+        "ansi-styles": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+            "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+            "dev": true
+        },
+        "any-observable": {
+            "version": "0.3.0",
+            "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz",
+            "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==",
+            "dev": true
+        },
+        "anymatch": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
+            "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
+            "dev": true,
+            "requires": {
+                "micromatch": "^3.1.4",
+                "normalize-path": "^2.1.1"
+            }
+        },
+        "append-transform": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
+            "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
+            "dev": true,
+            "requires": {
+                "default-require-extensions": "^2.0.0"
+            }
+        },
+        "aproba": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
+            "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=",
+            "dev": true
+        },
+        "are-we-there-yet": {
+            "version": "1.1.5",
+            "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
+            "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
+            "dev": true,
+            "requires": {
+                "delegates": "^1.0.0",
+                "readable-stream": "^2.0.6"
+            }
+        },
+        "argparse": {
+            "version": "1.0.10",
+            "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+            "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+            "dev": true,
+            "requires": {
+                "sprintf-js": "~1.0.2"
+            }
+        },
+        "aria-query": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
+            "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
+            "dev": true,
+            "requires": {
+                "ast-types-flow": "0.0.7",
+                "commander": "^2.11.0"
+            }
+        },
+        "arr-diff": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
+            "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
+            "dev": true
+        },
+        "arr-flatten": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+            "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
+            "dev": true
+        },
+        "arr-union": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
+            "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
+            "dev": true
+        },
+        "array-find-index": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
+            "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
+            "dev": true
+        },
+        "array-flatten": {
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
+            "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
+            "dev": true
+        },
+        "array-includes": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
+            "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
+            "dev": true,
+            "requires": {
+                "define-properties": "^1.1.2",
+                "es-abstract": "^1.7.0"
+            }
+        },
+        "array-union": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
+            "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
+            "dev": true,
+            "requires": {
+                "array-uniq": "^1.0.1"
+            }
+        },
+        "array-uniq": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
+            "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
+            "dev": true
+        },
+        "arraybuffer.slice": {
+            "version": "0.0.7",
+            "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
+            "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
+            "dev": true
+        },
+        "arrify": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+            "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+            "dev": true
+        },
+        "asn1": {
+            "version": "0.2.3",
+            "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
+            "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
+            "dev": true
+        },
+        "asn1.js": {
+            "version": "4.10.1",
+            "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
+            "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
+            "dev": true,
+            "requires": {
+                "bn.js": "^4.0.0",
+                "inherits": "^2.0.1",
+                "minimalistic-assert": "^1.0.0"
+            }
+        },
+        "assert": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
+            "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
+            "dev": true,
+            "requires": {
+                "util": "0.10.3"
+            },
+            "dependencies": {
+                "inherits": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+                    "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+                    "dev": true
+                },
+                "util": {
+                    "version": "0.10.3",
+                    "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+                    "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+                    "dev": true,
+                    "requires": {
+                        "inherits": "2.0.1"
+                    }
+                }
+            }
+        },
+        "assert-plus": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+            "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
+            "dev": true
+        },
+        "assign-symbols": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
+            "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
+            "dev": true
+        },
+        "ast-types": {
+            "version": "0.9.6",
+            "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
+            "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=",
+            "dev": true
+        },
+        "ast-types-flow": {
+            "version": "0.0.7",
+            "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
+            "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
+            "dev": true
+        },
+        "astral-regex": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
+            "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+            "dev": true
+        },
+        "async": {
+            "version": "1.5.2",
+            "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
+            "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
+            "dev": true
+        },
+        "async-each": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+            "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+            "dev": true
+        },
+        "async-foreach": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
+            "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
+            "dev": true
+        },
+        "async-limiter": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+            "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
+            "dev": true
+        },
+        "asynckit": {
+            "version": "0.4.0",
+            "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+            "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
+        },
+        "atob": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz",
+            "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
+            "dev": true
+        },
+        "autoprefixer": {
+            "version": "9.5.1",
+            "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz",
+            "integrity": "sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==",
+            "dev": true,
+            "requires": {
+                "browserslist": "^4.5.4",
+                "caniuse-lite": "^1.0.30000957",
+                "normalize-range": "^0.1.2",
+                "num2fraction": "^1.2.2",
+                "postcss": "^7.0.14",
+                "postcss-value-parser": "^3.3.1"
+            }
+        },
+        "aws-sign2": {
+            "version": "0.7.0",
+            "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+            "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
+            "dev": true
+        },
+        "aws4": {
+            "version": "1.7.0",
+            "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
+            "integrity": "sha1-1NDpudv8p3vwjusKikcVUP454ok=",
+            "dev": true
+        },
+        "axobject-query": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
+            "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
+            "dev": true,
+            "requires": {
+                "ast-types-flow": "0.0.7"
+            }
+        },
+        "babel-code-frame": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+            "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+            "dev": true,
+            "requires": {
+                "chalk": "^1.1.3",
+                "esutils": "^2.0.2",
+                "js-tokens": "^3.0.2"
+            }
+        },
+        "babel-generator": {
+            "version": "6.26.1",
+            "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
+            "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=",
+            "dev": true,
+            "requires": {
+                "babel-messages": "^6.23.0",
+                "babel-runtime": "^6.26.0",
+                "babel-types": "^6.26.0",
+                "detect-indent": "^4.0.0",
+                "jsesc": "^1.3.0",
+                "lodash": "^4.17.4",
+                "source-map": "^0.5.7",
+                "trim-right": "^1.0.1"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "source-map": {
+                    "version": "0.5.7",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+                    "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+                    "dev": true
+                }
+            }
+        },
+        "babel-loader": {
+            "version": "8.0.5",
+            "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz",
+            "integrity": "sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==",
+            "dev": true,
+            "requires": {
+                "find-cache-dir": "^2.0.0",
+                "loader-utils": "^1.0.2",
+                "mkdirp": "^0.5.1",
+                "util.promisify": "^1.0.0"
+            }
+        },
+        "babel-messages": {
+            "version": "6.23.0",
+            "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+            "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+            "dev": true,
+            "requires": {
+                "babel-runtime": "^6.22.0"
+            }
+        },
+        "babel-plugin-istanbul": {
+            "version": "5.1.4",
+            "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz",
+            "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==",
+            "dev": true,
+            "requires": {
+                "find-up": "^3.0.0",
+                "istanbul-lib-instrument": "^3.3.0",
+                "test-exclude": "^5.2.3"
+            },
+            "dependencies": {
+                "find-up": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+                    "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^3.0.0"
+                    }
+                },
+                "istanbul-lib-coverage": {
+                    "version": "2.0.5",
+                    "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
+                    "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
+                    "dev": true
+                },
+                "istanbul-lib-instrument": {
+                    "version": "3.3.0",
+                    "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
+                    "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
+                    "dev": true,
+                    "requires": {
+                        "@babel/generator": "^7.4.0",
+                        "@babel/parser": "^7.4.3",
+                        "@babel/template": "^7.4.0",
+                        "@babel/traverse": "^7.4.3",
+                        "@babel/types": "^7.4.0",
+                        "istanbul-lib-coverage": "^2.0.5",
+                        "semver": "^6.0.0"
+                    }
+                },
+                "locate-path": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+                    "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+                    "dev": true,
+                    "requires": {
+                        "p-locate": "^3.0.0",
+                        "path-exists": "^3.0.0"
+                    }
+                },
+                "p-limit": {
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+                    "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+                    "dev": true,
+                    "requires": {
+                        "p-try": "^2.0.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+                    "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+                    "dev": true,
+                    "requires": {
+                        "p-limit": "^2.0.0"
+                    }
+                },
+                "p-try": {
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+                    "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+                    "dev": true
+                },
+                "path-exists": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+                    "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+                    "dev": true
+                },
+                "semver": {
+                    "version": "6.1.3",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.3.tgz",
+                    "integrity": "sha512-aymF+56WJJMyXQHcd4hlK4N75rwj5RQpfW8ePlQnJsTYOBLlLbcIErR/G1s9SkIvKBqOudR3KAx4wEqP+F1hNQ==",
+                    "dev": true
+                }
+            }
+        },
+        "babel-polyfill": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
+            "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
+            "dev": true,
+            "requires": {
+                "babel-runtime": "^6.26.0",
+                "core-js": "^2.5.0",
+                "regenerator-runtime": "^0.10.5"
+            },
+            "dependencies": {
+                "regenerator-runtime": {
+                    "version": "0.10.5",
+                    "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
+                    "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
+                    "dev": true
+                }
+            }
+        },
+        "babel-runtime": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+            "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+            "dev": true,
+            "requires": {
+                "core-js": "^2.4.0",
+                "regenerator-runtime": "^0.11.0"
+            }
+        },
+        "babel-template": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+            "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+            "dev": true,
+            "requires": {
+                "babel-runtime": "^6.26.0",
+                "babel-traverse": "^6.26.0",
+                "babel-types": "^6.26.0",
+                "babylon": "^6.18.0",
+                "lodash": "^4.17.4"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "babel-traverse": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+            "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+            "dev": true,
+            "requires": {
+                "babel-code-frame": "^6.26.0",
+                "babel-messages": "^6.23.0",
+                "babel-runtime": "^6.26.0",
+                "babel-types": "^6.26.0",
+                "babylon": "^6.18.0",
+                "debug": "^2.6.8",
+                "globals": "^9.18.0",
+                "invariant": "^2.2.2",
+                "lodash": "^4.17.4"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "babel-types": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+            "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+            "dev": true,
+            "requires": {
+                "babel-runtime": "^6.26.0",
+                "esutils": "^2.0.2",
+                "lodash": "^4.17.4",
+                "to-fast-properties": "^1.0.3"
+            },
+            "dependencies": {
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "babylon": {
+            "version": "6.18.0",
+            "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+            "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=",
+            "dev": true
+        },
+        "backo2": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
+            "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
+            "dev": true
+        },
+        "bail": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz",
+            "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==",
+            "dev": true
+        },
+        "balanced-match": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+            "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+            "dev": true
+        },
+        "base": {
+            "version": "0.11.2",
+            "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
+            "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
+            "dev": true,
+            "requires": {
+                "cache-base": "^1.0.1",
+                "class-utils": "^0.3.5",
+                "component-emitter": "^1.2.1",
+                "define-property": "^1.0.0",
+                "isobject": "^3.0.1",
+                "mixin-deep": "^1.2.0",
+                "pascalcase": "^0.1.1"
+            },
+            "dependencies": {
+                "define-property": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "dev": true,
+                    "requires": {
+                        "is-descriptor": "^1.0.0"
+                    }
+                },
+                "is-accessor-descriptor": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+                    "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^6.0.0"
+                    }
+                },
+                "is-data-descriptor": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+                    "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^6.0.0"
+                    }
+                },
+                "is-descriptor": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+                    "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+                    "dev": true,
+                    "requires": {
+                        "is-accessor-descriptor": "^1.0.0",
+                        "is-data-descriptor": "^1.0.0",
+                        "kind-of": "^6.0.2"
+                    }
+                },
+                "isobject": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+                    "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+                    "dev": true
+                },
+                "kind-of": {
+                    "version": "6.0.2",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+                    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+                    "dev": true
+                }
+            }
+        },
+        "base64-arraybuffer": {
+            "version": "0.1.5",
+            "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
+            "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
+            "dev": true
+        },
+        "base64-js": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
+            "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
+            "dev": true
+        },
+        "base64id": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
+            "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
+            "dev": true
+        },
+        "batch": {
+            "version": "0.6.1",
+            "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+            "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
+            "dev": true
+        },
+        "bcrypt-pbkdf": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
+            "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
+            "dev": true,
+            "optional": true,
+            "requires": {
+                "tweetnacl": "^0.14.3"
+            }
+        },
+        "better-assert": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
+            "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
+            "dev": true,
+            "requires": {
+                "callsite": "1.0.0"
+            }
+        },
+        "big.js": {
+            "version": "5.2.2",
+            "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+            "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+            "dev": true
+        },
+        "binary-extensions": {
+            "version": "1.11.0",
+            "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
+            "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
+            "dev": true
+        },
+        "blob": {
+            "version": "0.0.5",
+            "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
+            "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
+            "dev": true
+        },
+        "block-stream": {
+            "version": "0.0.9",
+            "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+            "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
+            "dev": true,
+            "requires": {
+                "inherits": "~2.0.0"
+            }
+        },
+        "blocking-proxy": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
+            "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
+            "dev": true,
+            "requires": {
+                "minimist": "^1.2.0"
+            },
+            "dependencies": {
+                "minimist": {
+                    "version": "1.2.0",
+                    "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+                    "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+                    "dev": true
+                }
+            }
+        },
+        "bluebird": {
+            "version": "3.5.5",
+            "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
+            "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
+            "dev": true
+        },
+        "bn.js": {
+            "version": "4.11.8",
+            "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+            "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+            "dev": true
+        },
+        "body-parser": {
+            "version": "1.19.0",
+            "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
+            "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+            "dev": true,
+            "requires": {
+                "bytes": "3.1.0",
+                "content-type": "~1.0.4",
+                "debug": "2.6.9",
+                "depd": "~1.1.2",
+                "http-errors": "1.7.2",
+                "iconv-lite": "0.4.24",
+                "on-finished": "~2.3.0",
+                "qs": "6.7.0",
+                "raw-body": "2.4.0",
+                "type-is": "~1.6.17"
+            },
+            "dependencies": {
+                "bytes": {
+                    "version": "3.1.0",
+                    "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
+                    "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
+                    "dev": true
+                },
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "http-errors": {
+                    "version": "1.7.2",
+                    "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
+                    "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+                    "dev": true,
+                    "requires": {
+                        "depd": "~1.1.2",
+                        "inherits": "2.0.3",
+                        "setprototypeof": "1.1.1",
+                        "statuses": ">= 1.5.0 < 2",
+                        "toidentifier": "1.0.0"
+                    }
+                },
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "dev": true,
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                },
+                "mime-db": {
+                    "version": "1.40.0",
+                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+                    "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+                    "dev": true
+                },
+                "mime-types": {
+                    "version": "2.1.24",
+                    "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
+                    "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+                    "dev": true,
+                    "requires": {
+                        "mime-db": "1.40.0"
+                    }
+                },
+                "qs": {
+                    "version": "6.7.0",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
+                    "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+                    "dev": true
+                },
+                "setprototypeof": {
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
+                    "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
+                    "dev": true
+                },
+                "type-is": {
+                    "version": "1.6.18",
+                    "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+                    "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+                    "dev": true,
+                    "requires": {
+                        "media-typer": "0.3.0",
+                        "mime-types": "~2.1.24"
+                    }
+                }
+            }
+        },
+        "bonjour": {
+            "version": "3.5.0",
+            "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
+            "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
+            "dev": true,
+            "requires": {
+                "array-flatten": "^2.1.0",
+                "deep-equal": "^1.0.1",
+                "dns-equal": "^1.0.0",
+                "dns-txt": "^2.0.2",
+                "multicast-dns": "^6.0.1",
+                "multicast-dns-service-types": "^1.1.0"
+            }
+        },
+        "boolbase": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+            "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
+            "dev": true
+        },
+        "brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=",
+            "dev": true,
+            "requires": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "braces": {
+            "version": "2.3.2",
+            "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
+            "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+            "dev": true,
+            "requires": {
+                "arr-flatten": "^1.1.0",
+                "array-unique": "^0.3.2",
+                "extend-shallow": "^2.0.1",
+                "fill-range": "^4.0.0",
+                "isobject": "^3.0.1",
+                "repeat-element": "^1.1.2",
+                "snapdragon": "^0.8.1",
+                "snapdragon-node": "^2.0.1",
+                "split-string": "^3.0.2",
+                "to-regex": "^3.0.1"
+            },
+            "dependencies": {
+                "array-unique": {
+                    "version": "0.3.2",
+                    "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+                    "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+                    "dev": true
+                },
+                "extend-shallow": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "dev": true,
+                    "requires": {
+                        "is-extendable": "^0.1.0"
+                    }
+                }
+            }
+        },
+        "brorand": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+            "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+            "dev": true
+        },
+        "browserify-aes": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+            "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+            "dev": true,
+            "requires": {
+                "buffer-xor": "^1.0.3",
+                "cipher-base": "^1.0.0",
+                "create-hash": "^1.1.0",
+                "evp_bytestokey": "^1.0.3",
+                "inherits": "^2.0.1",
+                "safe-buffer": "^5.0.1"
+            }
+        },
+        "browserify-cipher": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+            "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+            "dev": true,
+            "requires": {
+                "browserify-aes": "^1.0.4",
+                "browserify-des": "^1.0.0",
+                "evp_bytestokey": "^1.0.0"
+            }
+        },
+        "browserify-des": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+            "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+            "dev": true,
+            "requires": {
+                "cipher-base": "^1.0.1",
+                "des.js": "^1.0.0",
+                "inherits": "^2.0.1",
+                "safe-buffer": "^5.1.2"
+            },
+            "dependencies": {
+                "safe-buffer": {
+                    "version": "5.1.2",
+                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                    "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+                    "dev": true
+                }
+            }
+        },
+        "browserify-rsa": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+            "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+            "dev": true,
+            "requires": {
+                "bn.js": "^4.1.0",
+                "randombytes": "^2.0.1"
+            }
+        },
+        "browserify-sign": {
+            "version": "4.0.4",
+            "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+            "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+            "dev": true,
+            "requires": {
+                "bn.js": "^4.1.1",
+                "browserify-rsa": "^4.0.0",
+                "create-hash": "^1.1.0",
+                "create-hmac": "^1.1.2",
+                "elliptic": "^6.0.0",
+                "inherits": "^2.0.1",
+                "parse-asn1": "^5.0.0"
+            }
+        },
+        "browserify-zlib": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+            "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+            "dev": true,
+            "requires": {
+                "pako": "~1.0.5"
+            }
+        },
+        "browserslist": {
+            "version": "4.5.5",
+            "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.5.5.tgz",
+            "integrity": "sha512-0QFO1r/2c792Ohkit5XI8Cm8pDtZxgNl2H6HU4mHrpYz7314pEYcsAVVatM0l/YmxPnEzh9VygXouj4gkFUTKA==",
+            "dev": true,
+            "requires": {
+                "caniuse-lite": "^1.0.30000960",
+                "electron-to-chromium": "^1.3.124",
+                "node-releases": "^1.1.14"
+            }
+        },
+        "browserstack": {
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.1.tgz",
+            "integrity": "sha512-O8VMT64P9NOLhuIoD4YngyxBURefaSdR4QdhG8l6HZ9VxtU7jc3m6jLufFwKA5gaf7fetfB2TnRJnMxyob+heg==",
+            "dev": true,
+            "requires": {
+                "https-proxy-agent": "^2.2.1"
+            }
+        },
+        "buffer": {
+            "version": "4.9.1",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+            "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
+            "dev": true,
+            "requires": {
+                "base64-js": "^1.0.2",
+                "ieee754": "^1.1.4",
+                "isarray": "^1.0.0"
+            }
+        },
+        "buffer-alloc": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
+            "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
+            "dev": true,
+            "requires": {
+                "buffer-alloc-unsafe": "^1.1.0",
+                "buffer-fill": "^1.0.0"
+            }
+        },
+        "buffer-alloc-unsafe": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
+            "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
+            "dev": true
+        },
+        "buffer-fill": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
+            "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=",
+            "dev": true
+        },
+        "buffer-from": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+            "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
+            "dev": true
+        },
+        "buffer-indexof": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
+            "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
+            "dev": true
+        },
+        "buffer-json": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz",
+            "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==",
+            "dev": true
+        },
+        "buffer-xor": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+            "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+            "dev": true
+        },
+        "builtin-modules": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+            "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+            "dev": true
+        },
+        "builtin-status-codes": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+            "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
+            "dev": true
+        },
+        "bytes": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
+            "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=",
+            "dev": true
+        },
+        "cacache": {
+            "version": "11.3.2",
+            "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.2.tgz",
+            "integrity": "sha512-E0zP4EPGDOaT2chM08Als91eYnf8Z+eH1awwwVsngUmgppfM5jjJ8l3z5vO5p5w/I3LsiXawb1sW0VY65pQABg==",
+            "dev": true,
+            "requires": {
+                "bluebird": "^3.5.3",
+                "chownr": "^1.1.1",
+                "figgy-pudding": "^3.5.1",
+                "glob": "^7.1.3",
+                "graceful-fs": "^4.1.15",
+                "lru-cache": "^5.1.1",
+                "mississippi": "^3.0.0",
+                "mkdirp": "^0.5.1",
+                "move-concurrently": "^1.0.1",
+                "promise-inflight": "^1.0.1",
+                "rimraf": "^2.6.2",
+                "ssri": "^6.0.1",
+                "unique-filename": "^1.1.1",
+                "y18n": "^4.0.0"
+            },
+            "dependencies": {
+                "bluebird": {
+                    "version": "3.5.4",
+                    "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz",
+                    "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==",
+                    "dev": true
+                },
+                "chownr": {
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz",
+                    "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==",
+                    "dev": true
+                },
+                "rimraf": {
+                    "version": "2.6.3",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+                    "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+                    "dev": true,
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                },
+                "y18n": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
+                    "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
+                    "dev": true
+                }
+            }
+        },
+        "cache-base": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
+            "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
+            "dev": true,
+            "requires": {
+                "collection-visit": "^1.0.0",
+                "component-emitter": "^1.2.1",
+                "get-value": "^2.0.6",
+                "has-value": "^1.0.0",
+                "isobject": "^3.0.1",
+                "set-value": "^2.0.0",
+                "to-object-path": "^0.3.0",
+                "union-value": "^1.0.0",
+                "unset-value": "^1.0.0"
+            },
+            "dependencies": {
+                "isobject": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+                    "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+                    "dev": true
+                }
+            }
+        },
+        "cache-loader": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-3.0.0.tgz",
+            "integrity": "sha512-VaSDv1VxKUc04aandtAJ85+CvdGrGYCPExAxNOVedt3tElJRj/xhS4tHw3Ifw7m+mbltzbBzU/6aLQA8gYIYJQ==",
+            "dev": true,
+            "requires": {
+                "buffer-json": "^2.0.0",
+                "find-cache-dir": "^2.1.0",
+                "loader-utils": "^1.1.0",
+                "mkdirp": "^0.5.1",
+                "neo-async": "^2.6.0",
+                "normalize-path": "^3.0.0",
+                "schema-utils": "^1.0.0"
+            },
+            "dependencies": {
+                "normalize-path": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+                    "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+                    "dev": true
+                }
+            }
+        },
+        "call-me-maybe": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
+            "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=",
+            "dev": true
+        },
+        "caller-callsite": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
+            "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=",
+            "dev": true,
+            "requires": {
+                "callsites": "^2.0.0"
+            }
+        },
+        "caller-path": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
+            "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=",
+            "dev": true,
+            "requires": {
+                "caller-callsite": "^2.0.0"
+            }
+        },
+        "callsite": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
+            "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=",
+            "dev": true
+        },
+        "callsites": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+            "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
+            "dev": true
+        },
+        "camel-case": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+            "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+            "dev": true,
+            "requires": {
+                "no-case": "^2.2.0",
+                "upper-case": "^1.1.1"
+            }
+        },
+        "camelcase": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
+            "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=",
+            "dev": true
+        },
+        "camelcase-keys": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
+            "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
+            "dev": true,
+            "requires": {
+                "camelcase": "^2.0.0",
+                "map-obj": "^1.0.0"
+            }
+        },
+        "caniuse-api": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+            "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
+            "dev": true,
+            "requires": {
+                "browserslist": "^4.0.0",
+                "caniuse-lite": "^1.0.0",
+                "lodash.memoize": "^4.1.2",
+                "lodash.uniq": "^4.5.0"
+            }
+        },
+        "caniuse-lite": {
+            "version": "1.0.30000963",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000963.tgz",
+            "integrity": "sha512-n4HUiullc7Lw0LyzpeLa2ffP8KxFBGdxqD/8G3bSL6oB758hZ2UE2CVK+tQN958tJIi0/tfpjAc67aAtoHgnrQ==",
+            "dev": true
+        },
+        "caseless": {
+            "version": "0.12.0",
+            "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+            "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
+            "dev": true
+        },
+        "ccount": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/ccount/-/ccount-1.0.3.tgz",
+            "integrity": "sha512-Jt9tIBkRc9POUof7QA/VwWd+58fKkEEfI+/t1/eOlxKM7ZhrczNzMFefge7Ai+39y1pR/pP6cI19guHy3FSLmw==",
+            "dev": true
+        },
+        "chalk": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+            "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+            "dev": true,
+            "requires": {
+                "ansi-styles": "^2.2.1",
+                "escape-string-regexp": "^1.0.2",
+                "has-ansi": "^2.0.0",
+                "strip-ansi": "^3.0.0",
+                "supports-color": "^2.0.0"
+            }
+        },
+        "character-entities": {
+            "version": "1.2.2",
+            "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.2.tgz",
+            "integrity": "sha512-sMoHX6/nBiy3KKfC78dnEalnpn0Az0oSNvqUWYTtYrhRI5iUIYsROU48G+E+kMFQzqXaJ8kHJZ85n7y6/PHgwQ==",
+            "dev": true
+        },
+        "character-entities-html4": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-1.1.2.tgz",
+            "integrity": "sha512-sIrXwyna2+5b0eB9W149izTPJk/KkJTg6mEzDGibwBUkyH1SbDa+nf515Ppdi3MaH35lW0JFJDWeq9Luzes1Iw==",
+            "dev": true
+        },
+        "character-entities-legacy": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.2.tgz",
+            "integrity": "sha512-9NB2VbXtXYWdXzqrvAHykE/f0QJxzaKIpZ5QzNZrrgQ7Iyxr2vnfS8fCBNVW9nUEZE0lo57nxKRqnzY/dKrwlA==",
+            "dev": true
+        },
+        "character-reference-invalid": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.2.tgz",
+            "integrity": "sha512-7I/xceXfKyUJmSAn/jw8ve/9DyOP7XxufNYLI9Px7CmsKgEUaZLUTax6nZxGQtaoiZCjpu6cHPj20xC/vqRReQ==",
+            "dev": true
+        },
+        "chardet": {
+            "version": "0.7.0",
+            "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+            "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
+            "dev": true
+        },
+        "chokidar": {
+            "version": "2.1.5",
+            "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.5.tgz",
+            "integrity": "sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A==",
+            "dev": true,
+            "requires": {
+                "anymatch": "^2.0.0",
+                "async-each": "^1.0.1",
+                "braces": "^2.3.2",
+                "fsevents": "^1.2.7",
+                "glob-parent": "^3.1.0",
+                "inherits": "^2.0.3",
+                "is-binary-path": "^1.0.0",
+                "is-glob": "^4.0.0",
+                "normalize-path": "^3.0.0",
+                "path-is-absolute": "^1.0.0",
+                "readdirp": "^2.2.1",
+                "upath": "^1.1.1"
+            },
+            "dependencies": {
+                "is-glob": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+                    "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+                    "dev": true,
+                    "requires": {
+                        "is-extglob": "^2.1.1"
+                    }
+                },
+                "normalize-path": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+                    "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+                    "dev": true
+                },
+                "readdirp": {
+                    "version": "2.2.1",
+                    "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
+                    "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
+                    "dev": true,
+                    "requires": {
+                        "graceful-fs": "^4.1.11",
+                        "micromatch": "^3.1.10",
+                        "readable-stream": "^2.0.2"
+                    }
+                },
+                "upath": {
+                    "version": "1.1.2",
+                    "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz",
+                    "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==",
+                    "dev": true
+                }
+            }
+        },
+        "chrome-trace-event": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.0.tgz",
+            "integrity": "sha512-xDbVgyfDTT2piup/h8dK/y4QZfJRSa73bw1WZ8b4XM1o7fsFubUVGYcE+1ANtOzJJELGpYoG2961z0Z6OAld9A==",
+            "dev": true,
+            "requires": {
+                "tslib": "^1.9.0"
+            },
+            "dependencies": {
+                "tslib": {
+                    "version": "1.9.3",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+                    "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
+                    "dev": true
+                }
+            }
+        },
+        "ci-info": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
+            "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
+            "dev": true
+        },
+        "cipher-base": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+            "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.1",
+                "safe-buffer": "^5.0.1"
+            }
+        },
+        "class-utils": {
+            "version": "0.3.6",
+            "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
+            "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+            "dev": true,
+            "requires": {
+                "arr-union": "^3.1.0",
+                "define-property": "^0.2.5",
+                "isobject": "^3.0.0",
+                "static-extend": "^0.1.1"
+            },
+            "dependencies": {
+                "define-property": {
+                    "version": "0.2.5",
+                    "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "dev": true,
+                    "requires": {
+                        "is-descriptor": "^0.1.0"
+                    }
+                },
+                "isobject": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+                    "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+                    "dev": true
+                }
+            }
+        },
+        "clean-css": {
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
+            "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
+            "dev": true,
+            "requires": {
+                "source-map": "~0.6.0"
+            },
+            "dependencies": {
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+                    "dev": true
+                }
+            }
+        },
+        "cli-cursor": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+            "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
+            "dev": true,
+            "requires": {
+                "restore-cursor": "^2.0.0"
+            }
+        },
+        "cli-truncate": {
+            "version": "0.2.1",
+            "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz",
+            "integrity": "sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ=",
+            "dev": true,
+            "requires": {
+                "slice-ansi": "0.0.4",
+                "string-width": "^1.0.1"
+            },
+            "dependencies": {
+                "slice-ansi": {
+                    "version": "0.0.4",
+                    "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz",
+                    "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=",
+                    "dev": true
+                }
+            }
+        },
+        "cli-width": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
+            "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
+            "dev": true
+        },
+        "cliui": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
+            "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
+            "dev": true,
+            "requires": {
+                "string-width": "^1.0.1",
+                "strip-ansi": "^3.0.1",
+                "wrap-ansi": "^2.0.0"
+            }
+        },
+        "clone-deep": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-2.0.2.tgz",
+            "integrity": "sha512-SZegPTKjCgpQH63E+eN6mVEEPdQBOUzjyJm5Pora4lrwWRFS8I0QAxV/KD6vV/i0WuijHZWQC1fMsPEdxfdVCQ==",
+            "dev": true,
+            "requires": {
+                "for-own": "^1.0.0",
+                "is-plain-object": "^2.0.4",
+                "kind-of": "^6.0.0",
+                "shallow-clone": "^1.0.0"
+            },
+            "dependencies": {
+                "kind-of": {
+                    "version": "6.0.2",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+                    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+                    "dev": true
+                }
+            }
+        },
+        "clone-regexp": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.1.tgz",
+            "integrity": "sha512-Fcij9IwRW27XedRIJnSOEupS7RVcXtObJXbcUOX93UCLqqOdRpkvzKywOOSizmEK/Is3S/RHX9dLdfo6R1Q1mw==",
+            "dev": true,
+            "requires": {
+                "is-regexp": "^1.0.0",
+                "is-supported-regexp-flag": "^1.0.0"
+            }
+        },
+        "co": {
+            "version": "4.6.0",
+            "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+            "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+            "dev": true
+        },
+        "coa": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
+            "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
+            "dev": true,
+            "requires": {
+                "@types/q": "^1.5.1",
+                "chalk": "^2.4.1",
+                "q": "^1.1.2"
+            },
+            "dependencies": {
+                "@types/q": {
+                    "version": "1.5.2",
+                    "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz",
+                    "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
+                    "dev": true
+                },
+                "ansi-styles": {
+                    "version": "3.2.1",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+                    "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+                    "dev": true,
+                    "requires": {
+                        "color-convert": "^1.9.0"
+                    }
+                },
+                "chalk": {
+                    "version": "2.4.2",
+                    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+                    "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-styles": "^3.2.1",
+                        "escape-string-regexp": "^1.0.5",
+                        "supports-color": "^5.3.0"
+                    }
+                },
+                "has-flag": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+                    "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+                    "dev": true
+                },
+                "supports-color": {
+                    "version": "5.5.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+                    "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+                    "dev": true,
+                    "requires": {
+                        "has-flag": "^3.0.0"
+                    }
+                }
+            }
+        },
+        "code-point-at": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
+            "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+            "dev": true
+        },
+        "collapse-white-space": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.4.tgz",
+            "integrity": "sha512-YfQ1tAUZm561vpYD+5eyWN8+UsceQbSrqqlc/6zDY2gtAE+uZLSdkkovhnGpmCThsvKBFakq4EdY/FF93E8XIw==",
+            "dev": true
+        },
+        "collection-visit": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
+            "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
+            "dev": true,
+            "requires": {
+                "map-visit": "^1.0.0",
+                "object-visit": "^1.0.0"
+            }
+        },
+        "color": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/color/-/color-3.1.1.tgz",
+            "integrity": "sha512-PvUltIXRjehRKPSy89VnDWFKY58xyhTLyxIg21vwQBI6qLwZNPmC8k3C1uytIgFKEpOIzN4y32iPm8231zFHIg==",
+            "dev": true,
+            "requires": {
+                "color-convert": "^1.9.1",
+                "color-string": "^1.5.2"
+            }
+        },
+        "color-convert": {
+            "version": "1.9.2",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz",
+            "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==",
+            "dev": true,
+            "requires": {
+                "color-name": "1.1.1"
+            }
+        },
+        "color-name": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz",
+            "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=",
+            "dev": true
+        },
+        "color-string": {
+            "version": "1.5.3",
+            "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz",
+            "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==",
+            "dev": true,
+            "requires": {
+                "color-name": "^1.0.0",
+                "simple-swizzle": "^0.2.2"
+            }
+        },
+        "colors": {
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz",
+            "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==",
+            "dev": true
+        },
+        "combined-stream": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
+            "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
+            "requires": {
+                "delayed-stream": "~1.0.0"
+            }
+        },
+        "commander": {
+            "version": "2.20.0",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+            "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+            "dev": true
+        },
+        "commondir": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+            "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+            "dev": true
+        },
+        "compare-versions": {
+            "version": "3.4.0",
+            "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.4.0.tgz",
+            "integrity": "sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg==",
+            "dev": true
+        },
+        "component-bind": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz",
+            "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=",
+            "dev": true
+        },
+        "component-emitter": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
+            "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY="
+        },
+        "component-inherit": {
+            "version": "0.0.3",
+            "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz",
+            "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=",
+            "dev": true
+        },
+        "compressible": {
+            "version": "2.0.17",
+            "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz",
+            "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==",
+            "dev": true,
+            "requires": {
+                "mime-db": ">= 1.40.0 < 2"
+            },
+            "dependencies": {
+                "mime-db": {
+                    "version": "1.40.0",
+                    "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
+                    "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
+                    "dev": true
+                }
+            }
+        },
+        "compression": {
+            "version": "1.7.4",
+            "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
+            "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+            "dev": true,
+            "requires": {
+                "accepts": "~1.3.5",
+                "bytes": "3.0.0",
+                "compressible": "~2.0.16",
+                "debug": "2.6.9",
+                "on-headers": "~1.0.2",
+                "safe-buffer": "5.1.2",
+                "vary": "~1.1.2"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "safe-buffer": {
+                    "version": "5.1.2",
+                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                    "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+                    "dev": true
+                }
+            }
+        },
+        "compression-webpack-plugin": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-2.0.0.tgz",
+            "integrity": "sha512-bDgd7oTUZC8EkRx8j0sjyCfeiO+e5sFcfgaFcjVhfQf5lLya7oY2BczxcJ7IUuVjz5m6fy8IECFmVFew3xLk8Q==",
+            "dev": true,
+            "requires": {
+                "cacache": "^11.2.0",
+                "find-cache-dir": "^2.0.0",
+                "neo-async": "^2.5.0",
+                "schema-utils": "^1.0.0",
+                "serialize-javascript": "^1.4.0",
+                "webpack-sources": "^1.0.1"
+            }
+        },
+        "concat-map": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+            "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+            "dev": true
+        },
+        "concat-stream": {
+            "version": "1.6.2",
+            "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+            "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+            "dev": true,
+            "requires": {
+                "buffer-from": "^1.0.0",
+                "inherits": "^2.0.3",
+                "readable-stream": "^2.2.2",
+                "typedarray": "^0.0.6"
+            }
+        },
+        "connect": {
+            "version": "3.7.0",
+            "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz",
+            "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==",
+            "dev": true,
+            "requires": {
+                "debug": "2.6.9",
+                "finalhandler": "1.1.2",
+                "parseurl": "~1.3.3",
+                "utils-merge": "1.0.1"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "parseurl": {
+                    "version": "1.3.3",
+                    "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+                    "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+                    "dev": true
+                }
+            }
+        },
+        "connect-history-api-fallback": {
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
+            "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
+            "dev": true
+        },
+        "console-browserify": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz",
+            "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=",
+            "dev": true,
+            "requires": {
+                "date-now": "^0.1.4"
+            }
+        },
+        "console-control-strings": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+            "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+            "dev": true
+        },
+        "constants-browserify": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+            "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
+            "dev": true
+        },
+        "contains-path": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
+            "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
+            "dev": true
+        },
+        "content-disposition": {
+            "version": "0.5.2",
+            "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+            "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+            "dev": true
+        },
+        "content-type": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+            "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
+            "dev": true
+        },
+        "convert-source-map": {
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
+            "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
+            "dev": true
+        },
+        "cookie": {
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+            "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+            "dev": true
+        },
+        "cookie-signature": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+            "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+            "dev": true
+        },
+        "cookiejar": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.1.tgz",
+            "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o="
+        },
+        "copy-concurrently": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
+            "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
+            "dev": true,
+            "requires": {
+                "aproba": "^1.1.1",
+                "fs-write-stream-atomic": "^1.0.8",
+                "iferr": "^0.1.5",
+                "mkdirp": "^0.5.1",
+                "rimraf": "^2.5.4",
+                "run-queue": "^1.0.0"
+            },
+            "dependencies": {
+                "rimraf": {
+                    "version": "2.6.3",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+                    "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+                    "dev": true,
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                }
+            }
+        },
+        "copy-descriptor": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
+            "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
+            "dev": true
+        },
+        "core-js": {
+            "version": "2.5.5",
+            "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz",
+            "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=",
+            "dev": true
+        },
+        "core-js-compat": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.1.tgz",
+            "integrity": "sha512-2pC3e+Ht/1/gD7Sim/sqzvRplMiRnFQVlPpDVaHtY9l7zZP7knamr3VRD6NyGfHd84MrDC0tAM9ulNxYMW0T3g==",
+            "dev": true,
+            "requires": {
+                "browserslist": "^4.5.4",
+                "core-js": "3.0.1",
+                "core-js-pure": "3.0.1",
+                "semver": "^6.0.0"
+            },
+            "dependencies": {
+                "core-js": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz",
+                    "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==",
+                    "dev": true
+                },
+                "semver": {
+                    "version": "6.0.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz",
+                    "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==",
+                    "dev": true
+                }
+            }
+        },
+        "core-js-pure": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.0.1.tgz",
+            "integrity": "sha512-mSxeQ6IghKW3MoyF4cz19GJ1cMm7761ON+WObSyLfTu/Jn3x7w4NwNFnrZxgl4MTSvYYepVLNuRtlB4loMwJ5g==",
+            "dev": true
+        },
+        "core-util-is": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+            "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+        },
+        "cosmiconfig": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.0.tgz",
+            "integrity": "sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g==",
+            "dev": true,
+            "requires": {
+                "import-fresh": "^2.0.0",
+                "is-directory": "^0.3.1",
+                "js-yaml": "^3.13.0",
+                "parse-json": "^4.0.0"
+            },
+            "dependencies": {
+                "parse-json": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+                    "dev": true,
+                    "requires": {
+                        "error-ex": "^1.3.1",
+                        "json-parse-better-errors": "^1.0.1"
+                    }
+                }
+            }
+        },
+        "create-ecdh": {
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
+            "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==",
+            "dev": true,
+            "requires": {
+                "bn.js": "^4.1.0",
+                "elliptic": "^6.0.0"
+            }
+        },
+        "create-hash": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+            "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+            "dev": true,
+            "requires": {
+                "cipher-base": "^1.0.1",
+                "inherits": "^2.0.1",
+                "md5.js": "^1.3.4",
+                "ripemd160": "^2.0.1",
+                "sha.js": "^2.4.0"
+            }
+        },
+        "create-hmac": {
+            "version": "1.1.7",
+            "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+            "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+            "dev": true,
+            "requires": {
+                "cipher-base": "^1.0.3",
+                "create-hash": "^1.1.0",
+                "inherits": "^2.0.1",
+                "ripemd160": "^2.0.0",
+                "safe-buffer": "^5.0.1",
+                "sha.js": "^2.4.8"
+            }
+        },
+        "cross-fetch": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.2.tgz",
+            "integrity": "sha512-a4Z0EJ5Nck6QtMy9ZqloLfpvu2uMV3sBfMCR+CgSBCZc6z5KR4bfEiD3dkepH8iZgJMXQpTqf8FjMmvu/GMFkg==",
+            "dev": true,
+            "requires": {
+                "node-fetch": "2.3.0",
+                "whatwg-fetch": "3.0.0"
+            }
+        },
+        "cross-spawn": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
+            "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
+            "dev": true,
+            "requires": {
+                "lru-cache": "^4.0.1",
+                "which": "^1.2.9"
+            },
+            "dependencies": {
+                "lru-cache": {
+                    "version": "4.1.5",
+                    "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+                    "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+                    "dev": true,
+                    "requires": {
+                        "pseudomap": "^1.0.2",
+                        "yallist": "^2.1.2"
+                    }
+                }
+            }
+        },
+        "crypto-browserify": {
+            "version": "3.12.0",
+            "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+            "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+            "dev": true,
+            "requires": {
+                "browserify-cipher": "^1.0.0",
+                "browserify-sign": "^4.0.0",
+                "create-ecdh": "^4.0.0",
+                "create-hash": "^1.1.0",
+                "create-hmac": "^1.1.0",
+                "diffie-hellman": "^5.0.0",
+                "inherits": "^2.0.1",
+                "pbkdf2": "^3.0.3",
+                "public-encrypt": "^4.0.0",
+                "randombytes": "^2.0.0",
+                "randomfill": "^1.0.3"
+            }
+        },
+        "css-color-names": {
+            "version": "0.0.4",
+            "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
+            "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
+            "dev": true
+        },
+        "css-declaration-sorter": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz",
+            "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==",
+            "dev": true,
+            "requires": {
+                "postcss": "^7.0.1",
+                "timsort": "^0.3.0"
+            }
+        },
+        "css-loader": {
+            "version": "2.1.1",
+            "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz",
+            "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==",
+            "dev": true,
+            "requires": {
+                "camelcase": "^5.2.0",
+                "icss-utils": "^4.1.0",
+                "loader-utils": "^1.2.3",
+                "normalize-path": "^3.0.0",
+                "postcss": "^7.0.14",
+                "postcss-modules-extract-imports": "^2.0.0",
+                "postcss-modules-local-by-default": "^2.0.6",
+                "postcss-modules-scope": "^2.1.0",
+                "postcss-modules-values": "^2.0.0",
+                "postcss-value-parser": "^3.3.0",
+                "schema-utils": "^1.0.0"
+            },
+            "dependencies": {
+                "camelcase": {
+                    "version": "5.3.1",
+                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+                    "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+                    "dev": true
+                },
+                "normalize-path": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+                    "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+                    "dev": true
+                }
+            }
+        },
+        "css-select": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+            "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
+            "dev": true,
+            "requires": {
+                "boolbase": "~1.0.0",
+                "css-what": "2.1",
+                "domutils": "1.5.1",
+                "nth-check": "~1.0.1"
+            }
+        },
+        "css-select-base-adapter": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
+            "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
+            "dev": true
+        },
+        "css-tree": {
+            "version": "1.0.0-alpha.28",
+            "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.28.tgz",
+            "integrity": "sha512-joNNW1gCp3qFFzj4St6zk+Wh/NBv0vM5YbEreZk0SD4S23S+1xBKb6cLDg2uj4P4k/GUMlIm6cKIDqIG+vdt0w==",
+            "dev": true,
+            "requires": {
+                "mdn-data": "~1.1.0",
+                "source-map": "^0.5.3"
+            },
+            "dependencies": {
+                "source-map": {
+                    "version": "0.5.7",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+                    "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+                    "dev": true
+                }
+            }
+        },
+        "css-unit-converter": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz",
+            "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=",
+            "dev": true
+        },
+        "css-url-regex": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz",
+            "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=",
+            "dev": true
+        },
+        "css-what": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
+            "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
+            "dev": true
+        },
+        "cssesc": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+            "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+            "dev": true
+        },
+        "cssnano": {
+            "version": "4.1.10",
+            "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz",
+            "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==",
+            "dev": true,
+            "requires": {
+                "cosmiconfig": "^5.0.0",
+                "cssnano-preset-default": "^4.0.7",
+                "is-resolvable": "^1.0.0",
+                "postcss": "^7.0.0"
+            }
+        },
+        "cssnano-preset-default": {
+            "version": "4.0.7",
+            "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz",
+            "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==",
+            "dev": true,
+            "requires": {
+                "css-declaration-sorter": "^4.0.1",
+                "cssnano-util-raw-cache": "^4.0.1",
+                "postcss": "^7.0.0",
+                "postcss-calc": "^7.0.1",
+                "postcss-colormin": "^4.0.3",
+                "postcss-convert-values": "^4.0.1",
+                "postcss-discard-comments": "^4.0.2",
+                "postcss-discard-duplicates": "^4.0.2",
+                "postcss-discard-empty": "^4.0.1",
+                "postcss-discard-overridden": "^4.0.1",
+                "postcss-merge-longhand": "^4.0.11",
+                "postcss-merge-rules": "^4.0.3",
+                "postcss-minify-font-values": "^4.0.2",
+                "postcss-minify-gradients": "^4.0.2",
+                "postcss-minify-params": "^4.0.2",
+                "postcss-minify-selectors": "^4.0.2",
+                "postcss-normalize-charset": "^4.0.1",
+                "postcss-normalize-display-values": "^4.0.2",
+                "postcss-normalize-positions": "^4.0.2",
+                "postcss-normalize-repeat-style": "^4.0.2",
+                "postcss-normalize-string": "^4.0.2",
+                "postcss-normalize-timing-functions": "^4.0.2",
+                "postcss-normalize-unicode": "^4.0.1",
+                "postcss-normalize-url": "^4.0.1",
+                "postcss-normalize-whitespace": "^4.0.2",
+                "postcss-ordered-values": "^4.1.2",
+                "postcss-reduce-initial": "^4.0.3",
+                "postcss-reduce-transforms": "^4.0.2",
+                "postcss-svgo": "^4.0.2",
+                "postcss-unique-selectors": "^4.0.1"
+            }
+        },
+        "cssnano-util-get-arguments": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz",
+            "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=",
+            "dev": true
+        },
+        "cssnano-util-get-match": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz",
+            "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=",
+            "dev": true
+        },
+        "cssnano-util-raw-cache": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz",
+            "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==",
+            "dev": true,
+            "requires": {
+                "postcss": "^7.0.0"
+            }
+        },
+        "cssnano-util-same-parent": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz",
+            "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==",
+            "dev": true
+        },
+        "csso": {
+            "version": "3.5.1",
+            "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
+            "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==",
+            "dev": true,
+            "requires": {
+                "css-tree": "1.0.0-alpha.29"
+            },
+            "dependencies": {
+                "css-tree": {
+                    "version": "1.0.0-alpha.29",
+                    "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
+                    "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==",
+                    "dev": true,
+                    "requires": {
+                        "mdn-data": "~1.1.0",
+                        "source-map": "^0.5.3"
+                    }
+                },
+                "source-map": {
+                    "version": "0.5.7",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+                    "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+                    "dev": true
+                }
+            }
+        },
+        "currently-unhandled": {
+            "version": "0.4.1",
+            "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
+            "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
+            "dev": true,
+            "requires": {
+                "array-find-index": "^1.0.1"
+            }
+        },
+        "custom-event": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz",
+            "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=",
+            "dev": true
+        },
+        "cyclist": {
+            "version": "0.2.2",
+            "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
+            "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=",
+            "dev": true
+        },
+        "damerau-levenshtein": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.4.tgz",
+            "integrity": "sha1-AxkcQyy27qFou3fzpV/9zLiXhRQ=",
+            "dev": true
+        },
+        "dashdash": {
+            "version": "1.14.1",
+            "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+            "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
+            "dev": true,
+            "requires": {
+                "assert-plus": "^1.0.0"
+            }
+        },
+        "date-fns": {
+            "version": "1.30.1",
+            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+            "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==",
+            "dev": true
+        },
+        "date-format": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/date-format/-/date-format-2.0.0.tgz",
+            "integrity": "sha512-M6UqVvZVgFYqZL1SfHsRGIQSz3ZL+qgbsV5Lp1Vj61LZVYuEwcMXYay7DRDtYs2HQQBK5hQtQ0fD9aEJ89V0LA==",
+            "dev": true
+        },
+        "date-now": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz",
+            "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=",
+            "dev": true
+        },
         "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.1"
-          }
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+            "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
+            "requires": {
+                "ms": "2.0.0"
+            }
+        },
+        "decamelize": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+            "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+            "dev": true
+        },
+        "decamelize-keys": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz",
+            "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=",
+            "dev": true,
+            "requires": {
+                "decamelize": "^1.1.0",
+                "map-obj": "^1.0.0"
+            }
+        },
+        "decode-uri-component": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
+            "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
+            "dev": true
+        },
+        "dedent": {
+            "version": "0.7.0",
+            "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
+            "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
+            "dev": true
+        },
+        "deep-equal": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+            "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
+            "dev": true
+        },
+        "deep-is": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
+            "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
+            "dev": true
+        },
+        "default-gateway": {
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
+            "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
+            "dev": true,
+            "requires": {
+                "execa": "^1.0.0",
+                "ip-regex": "^2.1.0"
+            }
+        },
+        "default-require-extensions": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz",
+            "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=",
+            "dev": true,
+            "requires": {
+                "strip-bom": "^3.0.0"
+            },
+            "dependencies": {
+                "strip-bom": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+                    "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+                    "dev": true
+                }
+            }
+        },
+        "define-properties": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+            "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+            "dev": true,
+            "requires": {
+                "object-keys": "^1.0.12"
+            }
+        },
+        "define-property": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
+            "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
+            "dev": true,
+            "requires": {
+                "is-descriptor": "^1.0.2",
+                "isobject": "^3.0.1"
+            },
+            "dependencies": {
+                "is-accessor-descriptor": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+                    "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^6.0.0"
+                    }
+                },
+                "is-data-descriptor": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+                    "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^6.0.0"
+                    }
+                },
+                "is-descriptor": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+                    "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+                    "dev": true,
+                    "requires": {
+                        "is-accessor-descriptor": "^1.0.0",
+                        "is-data-descriptor": "^1.0.0",
+                        "kind-of": "^6.0.2"
+                    }
+                },
+                "isobject": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+                    "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+                    "dev": true
+                },
+                "kind-of": {
+                    "version": "6.0.2",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+                    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+                    "dev": true
+                }
+            }
+        },
+        "del": {
+            "version": "2.2.2",
+            "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz",
+            "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=",
+            "dev": true,
+            "requires": {
+                "globby": "^5.0.0",
+                "is-path-cwd": "^1.0.0",
+                "is-path-in-cwd": "^1.0.0",
+                "object-assign": "^4.0.1",
+                "pify": "^2.0.0",
+                "pinkie-promise": "^2.0.0",
+                "rimraf": "^2.2.8"
+            }
+        },
+        "delayed-stream": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+            "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
+        },
+        "delegates": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+            "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+            "dev": true
+        },
+        "depd": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+            "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+            "dev": true
+        },
+        "des.js": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+            "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.1",
+                "minimalistic-assert": "^1.0.0"
+            }
+        },
+        "destroy": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+            "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+            "dev": true
+        },
+        "detect-file": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
+            "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
+            "dev": true
+        },
+        "detect-indent": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+            "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+            "dev": true,
+            "requires": {
+                "repeating": "^2.0.0"
+            }
+        },
+        "detect-node": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+            "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
+            "dev": true
+        },
+        "di": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz",
+            "integrity": "sha1-gGZJMmzqp8qjMG112YXqJ0i6kTw=",
+            "dev": true
+        },
+        "diffie-hellman": {
+            "version": "5.0.3",
+            "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+            "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+            "dev": true,
+            "requires": {
+                "bn.js": "^4.1.0",
+                "miller-rabin": "^4.0.0",
+                "randombytes": "^2.0.0"
+            }
+        },
+        "dir-glob": {
+            "version": "2.2.2",
+            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
+            "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
+            "dev": true,
+            "requires": {
+                "path-type": "^3.0.0"
+            },
+            "dependencies": {
+                "path-type": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
+                    "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+                    "dev": true,
+                    "requires": {
+                        "pify": "^3.0.0"
+                    }
+                },
+                "pify": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
+                    "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+                    "dev": true
+                }
+            }
+        },
+        "dns-equal": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
+            "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=",
+            "dev": true
+        },
+        "dns-packet": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
+            "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
+            "dev": true,
+            "requires": {
+                "ip": "^1.1.0",
+                "safe-buffer": "^5.0.1"
+            }
+        },
+        "dns-txt": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
+            "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
+            "dev": true,
+            "requires": {
+                "buffer-indexof": "^1.0.0"
+            }
+        },
+        "doctrine": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+            "dev": true,
+            "requires": {
+                "esutils": "^2.0.2"
+            }
+        },
+        "dom-converter": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+            "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+            "dev": true,
+            "requires": {
+                "utila": "~0.4"
+            }
+        },
+        "dom-serialize": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz",
+            "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=",
+            "dev": true,
+            "requires": {
+                "custom-event": "~1.0.0",
+                "ent": "~2.2.0",
+                "extend": "^3.0.0",
+                "void-elements": "^2.0.0"
+            }
+        },
+        "dom-serializer": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
+            "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
+            "dev": true,
+            "requires": {
+                "domelementtype": "^1.3.0",
+                "entities": "^1.1.1"
+            }
+        },
+        "domain-browser": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+            "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+            "dev": true
+        },
+        "domelementtype": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
+            "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
+            "dev": true
+        },
+        "domhandler": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
+            "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
+            "dev": true,
+            "requires": {
+                "domelementtype": "1"
+            }
+        },
+        "domutils": {
+            "version": "1.5.1",
+            "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
+            "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
+            "dev": true,
+            "requires": {
+                "dom-serializer": "0",
+                "domelementtype": "1"
+            }
+        },
+        "dot-prop": {
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz",
+            "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==",
+            "dev": true,
+            "requires": {
+                "is-obj": "^1.0.0"
+            }
+        },
+        "dtsgenerator": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/dtsgenerator/-/dtsgenerator-2.0.6.tgz",
+            "integrity": "sha512-vLTiJpLfV6zrngD9CoVc8nrn/Veg/92acerp17iTDyqTkLLAjj4B2LmwhJPbIwq7nbTEFE3f2bm4kehuXvCPoQ==",
+            "dev": true,
+            "requires": {
+                "commander": "^2.19.0",
+                "cross-fetch": "^3.0.1",
+                "debug": "^4.1.1",
+                "glob": "^7.1.3",
+                "js-yaml": "^3.12.1",
+                "mkdirp": "^0.5.1",
+                "tslib": "^1.9.3"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
+                },
+                "ms": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+                    "dev": true
+                },
+                "tslib": {
+                    "version": "1.9.3",
+                    "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz",
+                    "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==",
+                    "dev": true
+                }
+            }
+        },
+        "duplexify": {
+            "version": "3.7.1",
+            "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
+            "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+            "dev": true,
+            "requires": {
+                "end-of-stream": "^1.0.0",
+                "inherits": "^2.0.1",
+                "readable-stream": "^2.0.0",
+                "stream-shift": "^1.0.0"
+            }
+        },
+        "ecc-jsbn": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz",
+            "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=",
+            "dev": true,
+            "optional": true,
+            "requires": {
+                "jsbn": "~0.1.0"
+            }
+        },
+        "ee-first": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+            "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+            "dev": true
+        },
+        "electron-to-chromium": {
+            "version": "1.3.127",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.127.tgz",
+            "integrity": "sha512-1o25iFRf/dbgauTWalEzmD1EmRN3a2CzP/K7UVpYLEBduk96LF0FyUdCcf4Ry2mAWJ1VxyblFjC93q6qlLwA2A==",
+            "dev": true
+        },
+        "elegant-spinner": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz",
+            "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=",
+            "dev": true
+        },
+        "elliptic": {
+            "version": "6.4.1",
+            "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz",
+            "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==",
+            "dev": true,
+            "requires": {
+                "bn.js": "^4.4.0",
+                "brorand": "^1.0.1",
+                "hash.js": "^1.0.0",
+                "hmac-drbg": "^1.0.0",
+                "inherits": "^2.0.1",
+                "minimalistic-assert": "^1.0.0",
+                "minimalistic-crypto-utils": "^1.0.0"
+            }
+        },
+        "emoji-regex": {
+            "version": "7.0.3",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
+            "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
+            "dev": true
+        },
+        "emojis-list": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
+            "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=",
+            "dev": true
+        },
+        "encodeurl": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+            "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+            "dev": true
+        },
+        "end-of-stream": {
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
+            "integrity": "sha1-7SljTRm6ukY7bOa4CjchPqtx7EM=",
+            "dev": true,
+            "requires": {
+                "once": "^1.4.0"
+            }
+        },
+        "engine.io": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.2.1.tgz",
+            "integrity": "sha512-+VlKzHzMhaU+GsCIg4AoXF1UdDFjHHwMmMKqMJNDNLlUlejz58FCy4LBqB2YVJskHGYl06BatYWKP2TVdVXE5w==",
+            "dev": true,
+            "requires": {
+                "accepts": "~1.3.4",
+                "base64id": "1.0.0",
+                "cookie": "0.3.1",
+                "debug": "~3.1.0",
+                "engine.io-parser": "~2.1.0",
+                "ws": "~3.3.1"
+            }
+        },
+        "engine.io-client": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.2.1.tgz",
+            "integrity": "sha512-y5AbkytWeM4jQr7m/koQLc5AxpRKC1hEVUb/s1FUAWEJq5AzJJ4NLvzuKPuxtDi5Mq755WuDvZ6Iv2rXj4PTzw==",
+            "dev": true,
+            "requires": {
+                "component-emitter": "1.2.1",
+                "component-inherit": "0.0.3",
+                "debug": "~3.1.0",
+                "engine.io-parser": "~2.1.1",
+                "has-cors": "1.1.0",
+                "indexof": "0.0.1",
+                "parseqs": "0.0.5",
+                "parseuri": "0.0.5",
+                "ws": "~3.3.1",
+                "xmlhttprequest-ssl": "~1.5.4",
+                "yeast": "0.1.2"
+            }
+        },
+        "engine.io-parser": {
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz",
+            "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==",
+            "dev": true,
+            "requires": {
+                "after": "0.8.2",
+                "arraybuffer.slice": "~0.0.7",
+                "base64-arraybuffer": "0.1.5",
+                "blob": "0.0.5",
+                "has-binary2": "~1.0.2"
+            }
+        },
+        "enhanced-resolve": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz",
+            "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==",
+            "dev": true,
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "memory-fs": "^0.4.0",
+                "tapable": "^1.0.0"
+            }
+        },
+        "ent": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz",
+            "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=",
+            "dev": true
+        },
+        "entities": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
+            "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
+            "dev": true
+        },
+        "errno": {
+            "version": "0.1.7",
+            "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
+            "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
+            "dev": true,
+            "requires": {
+                "prr": "~1.0.1"
+            }
+        },
+        "error-ex": {
+            "version": "1.3.1",
+            "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz",
+            "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=",
+            "dev": true,
+            "requires": {
+                "is-arrayish": "^0.2.1"
+            }
+        },
+        "es-abstract": {
+            "version": "1.13.0",
+            "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
+            "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
+            "dev": true,
+            "requires": {
+                "es-to-primitive": "^1.2.0",
+                "function-bind": "^1.1.1",
+                "has": "^1.0.3",
+                "is-callable": "^1.1.4",
+                "is-regex": "^1.0.4",
+                "object-keys": "^1.0.12"
+            }
+        },
+        "es-to-primitive": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
+            "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
+            "dev": true,
+            "requires": {
+                "is-callable": "^1.1.4",
+                "is-date-object": "^1.0.1",
+                "is-symbol": "^1.0.2"
+            }
+        },
+        "es6-promise": {
+            "version": "4.2.4",
+            "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
+            "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ==",
+            "dev": true
+        },
+        "es6-promisify": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+            "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+            "dev": true,
+            "requires": {
+                "es6-promise": "^4.0.3"
+            }
+        },
+        "es6-templates": {
+            "version": "0.2.3",
+            "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz",
+            "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=",
+            "dev": true,
+            "requires": {
+                "recast": "~0.11.12",
+                "through": "~2.3.6"
+            }
+        },
+        "escape-html": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+            "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+            "dev": true
+        },
+        "escape-string-regexp": {
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+            "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+            "dev": true
+        },
+        "eslint": {
+            "version": "5.14.1",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.14.1.tgz",
+            "integrity": "sha512-CyUMbmsjxedx8B0mr79mNOqetvkbij/zrXnFeK2zc3pGRn3/tibjiNAv/3UxFEyfMDjh+ZqTrJrEGBFiGfD5Og==",
+            "dev": true,
+            "requires": {
+                "@babel/code-frame": "^7.0.0",
+                "ajv": "^6.9.1",
+                "chalk": "^2.1.0",
+                "cross-spawn": "^6.0.5",
+                "debug": "^4.0.1",
+                "doctrine": "^3.0.0",
+                "eslint-scope": "^4.0.0",
+                "eslint-utils": "^1.3.1",
+                "eslint-visitor-keys": "^1.0.0",
+                "espree": "^5.0.1",
+                "esquery": "^1.0.1",
+                "esutils": "^2.0.2",
+                "file-entry-cache": "^5.0.1",
+                "functional-red-black-tree": "^1.0.1",
+                "glob": "^7.1.2",
+                "globals": "^11.7.0",
+                "ignore": "^4.0.6",
+                "import-fresh": "^3.0.0",
+                "imurmurhash": "^0.1.4",
+                "inquirer": "^6.2.2",
+                "js-yaml": "^3.12.0",
+                "json-stable-stringify-without-jsonify": "^1.0.1",
+                "levn": "^0.3.0",
+                "lodash": "^4.17.11",
+                "minimatch": "^3.0.4",
+                "mkdirp": "^0.5.1",
+                "natural-compare": "^1.4.0",
+                "optionator": "^0.8.2",
+                "path-is-inside": "^1.0.2",
+                "progress": "^2.0.0",
+                "regexpp": "^2.0.1",
+                "semver": "^5.5.1",
+                "strip-ansi": "^4.0.0",
+                "strip-json-comments": "^2.0.1",
+                "table": "^5.2.3",
+                "text-table": "^0.2.0"
+            },
+            "dependencies": {
+                "ajv": {
+                    "version": "6.10.0",
+                    "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
+                    "integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
+                    "dev": true,
+                    "requires": {
+                        "fast-deep-equal": "^2.0.1",
+                        "fast-json-stable-stringify": "^2.0.0",
+                        "json-schema-traverse": "^0.4.1",
+                        "uri-js": "^4.2.2"
+                    }
+                },
+                "ansi-regex": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+                    "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+                    "dev": true
+                },
+                "ansi-styles": {
+                    "version": "3.2.1",
+                    "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+                    "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+                    "dev": true,
+                    "requires": {
+                        "color-convert": "^1.9.0"
+                    }
+                },
+                "chalk": {
+                    "version": "2.4.2",
+                    "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+                    "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+                    "dev": true,
+                    "requires": {
+                        "ansi-styles": "^3.2.1",
+                        "escape-string-regexp": "^1.0.5",
+                        "supports-color": "^5.3.0"
+                    }
+                },
+                "cross-spawn": {
+                    "version": "6.0.5",
+                    "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+                    "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+                    "dev": true,
+                    "requires": {
+                        "nice-try": "^1.0.4",
+                        "path-key": "^2.0.1",
+                        "semver": "^5.5.0",
+                        "shebang-command": "^1.2.0",
+                        "which": "^1.2.9"
+                    }
+                },
+                "debug": {
+                    "version": "4.1.1",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+                    "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
+                },
+                "fast-deep-equal": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
+                    "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
+                    "dev": true
+                },
+                "globals": {
+                    "version": "11.12.0",
+                    "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+                    "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+                    "dev": true
+                },
+                "has-flag": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+                    "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+                    "dev": true
+                },
+                "import-fresh": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.0.0.tgz",
+                    "integrity": "sha512-pOnA9tfM3Uwics+SaBLCNyZZZbK+4PTu0OPZtLlMIrv17EdBoC15S9Kn8ckJ9TZTyKb3ywNE5y1yeDxxGA7nTQ==",
+                    "dev": true,
+                    "requires": {
+                        "parent-module": "^1.0.0",
+                        "resolve-from": "^4.0.0"
+                    }
+                },
+                "json-schema-traverse": {
+                    "version": "0.4.1",
+                    "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+                    "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+                    "dev": true
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "ms": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+                    "dev": true
+                },
+                "semver": {
+                    "version": "5.7.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+                    "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+                    "dev": true
+                },
+                "strip-ansi": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+                    "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+                    "dev": true,
+                    "requires": {
+                        "ansi-regex": "^3.0.0"
+                    }
+                },
+                "supports-color": {
+                    "version": "5.5.0",
+                    "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+                    "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+                    "dev": true,
+                    "requires": {
+                        "has-flag": "^3.0.0"
+                    }
+                },
+                "which": {
+                    "version": "1.3.1",
+                    "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+                    "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+                    "dev": true,
+                    "requires": {
+                        "isexe": "^2.0.0"
+                    }
+                }
+            }
+        },
+        "eslint-config-airbnb": {
+            "version": "17.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-17.1.0.tgz",
+            "integrity": "sha512-R9jw28hFfEQnpPau01NO5K/JWMGLi6aymiF6RsnMURjTk+MqZKllCqGK/0tOvHkPi/NWSSOU2Ced/GX++YxLnw==",
+            "dev": true,
+            "requires": {
+                "eslint-config-airbnb-base": "^13.1.0",
+                "object.assign": "^4.1.0",
+                "object.entries": "^1.0.4"
+            }
+        },
+        "eslint-config-airbnb-base": {
+            "version": "13.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz",
+            "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==",
+            "dev": true,
+            "requires": {
+                "eslint-restricted-globals": "^0.1.1",
+                "object.assign": "^4.1.0",
+                "object.entries": "^1.0.4"
+            }
+        },
+        "eslint-import-resolver-node": {
+            "version": "0.3.2",
+            "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz",
+            "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==",
+            "dev": true,
+            "requires": {
+                "debug": "^2.6.9",
+                "resolve": "^1.5.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "resolve": {
+                    "version": "1.10.1",
+                    "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz",
+                    "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==",
+                    "dev": true,
+                    "requires": {
+                        "path-parse": "^1.0.6"
+                    }
+                }
+            }
+        },
+        "eslint-module-utils": {
+            "version": "2.4.0",
+            "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz",
+            "integrity": "sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw==",
+            "dev": true,
+            "requires": {
+                "debug": "^2.6.8",
+                "pkg-dir": "^2.0.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "find-up": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^2.0.0"
+                    }
+                },
+                "pkg-dir": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz",
+                    "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^2.1.0"
+                    }
+                }
+            }
+        },
+        "eslint-plugin-import": {
+            "version": "2.16.0",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz",
+            "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==",
+            "dev": true,
+            "requires": {
+                "contains-path": "^0.1.0",
+                "debug": "^2.6.9",
+                "doctrine": "1.5.0",
+                "eslint-import-resolver-node": "^0.3.2",
+                "eslint-module-utils": "^2.3.0",
+                "has": "^1.0.3",
+                "lodash": "^4.17.11",
+                "minimatch": "^3.0.4",
+                "read-pkg-up": "^2.0.0",
+                "resolve": "^1.9.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "doctrine": {
+                    "version": "1.5.0",
+                    "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+                    "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
+                    "dev": true,
+                    "requires": {
+                        "esutils": "^2.0.2",
+                        "isarray": "^1.0.0"
+                    }
+                },
+                "find-up": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
+                    "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^2.0.0"
+                    }
+                },
+                "load-json-file": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+                    "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
+                    "dev": true,
+                    "requires": {
+                        "graceful-fs": "^4.1.2",
+                        "parse-json": "^2.2.0",
+                        "pify": "^2.0.0",
+                        "strip-bom": "^3.0.0"
+                    }
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                },
+                "path-type": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
+                    "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
+                    "dev": true,
+                    "requires": {
+                        "pify": "^2.0.0"
+                    }
+                },
+                "read-pkg": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
+                    "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
+                    "dev": true,
+                    "requires": {
+                        "load-json-file": "^2.0.0",
+                        "normalize-package-data": "^2.3.2",
+                        "path-type": "^2.0.0"
+                    }
+                },
+                "read-pkg-up": {
+                    "version": "2.0.0",
+                    "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
+                    "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^2.0.0",
+                        "read-pkg": "^2.0.0"
+                    }
+                },
+                "resolve": {
+                    "version": "1.10.1",
+                    "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz",
+                    "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==",
+                    "dev": true,
+                    "requires": {
+                        "path-parse": "^1.0.6"
+                    }
+                },
+                "strip-bom": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+                    "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=",
+                    "dev": true
+                }
+            }
+        },
+        "eslint-plugin-jsx-a11y": {
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.2.1.tgz",
+            "integrity": "sha512-cjN2ObWrRz0TTw7vEcGQrx+YltMvZoOEx4hWU8eEERDnBIU00OTq7Vr+jA7DFKxiwLNv4tTh5Pq2GUNEa8b6+w==",
+            "dev": true,
+            "requires": {
+                "aria-query": "^3.0.0",
+                "array-includes": "^3.0.3",
+                "ast-types-flow": "^0.0.7",
+                "axobject-query": "^2.0.2",
+                "damerau-levenshtein": "^1.0.4",
+                "emoji-regex": "^7.0.2",
+                "has": "^1.0.3",
+                "jsx-ast-utils": "^2.0.1"
+            }
+        },
+        "eslint-plugin-react": {
+            "version": "7.12.4",
+            "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.12.4.tgz",
+            "integrity": "sha512-1puHJkXJY+oS1t467MjbqjvX53uQ05HXwjqDgdbGBqf5j9eeydI54G3KwiJmWciQ0HTBacIKw2jgwSBSH3yfgQ==",
+            "dev": true,
+            "requires": {
+                "array-includes": "^3.0.3",
+                "doctrine": "^2.1.0",
+                "has": "^1.0.3",
+                "jsx-ast-utils": "^2.0.1",
+                "object.fromentries": "^2.0.0",
+                "prop-types": "^15.6.2",
+                "resolve": "^1.9.0"
+            },
+            "dependencies": {
+                "doctrine": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+                    "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+                    "dev": true,
+                    "requires": {
+                        "esutils": "^2.0.2"
+                    }
+                },
+                "resolve": {
+                    "version": "1.10.1",
+                    "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz",
+                    "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==",
+                    "dev": true,
+                    "requires": {
+                        "path-parse": "^1.0.6"
+                    }
+                }
+            }
+        },
+        "eslint-restricted-globals": {
+            "version": "0.1.1",
+            "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz",
+            "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=",
+            "dev": true
+        },
+        "eslint-scope": {
+            "version": "4.0.3",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
+            "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+            "dev": true,
+            "requires": {
+                "esrecurse": "^4.1.0",
+                "estraverse": "^4.1.1"
+            }
+        },
+        "eslint-utils": {
+            "version": "1.4.2",
+            "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
+            "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
+            "dev": true,
+            "requires": {
+                "eslint-visitor-keys": "^1.0.0"
+            }
+        },
+        "eslint-visitor-keys": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+            "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+            "dev": true
+        },
+        "espree": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz",
+            "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==",
+            "dev": true,
+            "requires": {
+                "acorn": "^6.0.7",
+                "acorn-jsx": "^5.0.0",
+                "eslint-visitor-keys": "^1.0.0"
+            }
+        },
+        "esprima": {
+            "version": "3.1.3",
+            "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+            "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=",
+            "dev": true
+        },
+        "esquery": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz",
+            "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^4.0.0"
+            }
+        },
+        "esrecurse": {
+            "version": "4.2.1",
+            "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
+            "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
+            "dev": true,
+            "requires": {
+                "estraverse": "^4.1.0"
+            }
+        },
+        "estraverse": {
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+            "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
+            "dev": true
+        },
+        "esutils": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+            "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+            "dev": true
+        },
+        "etag": {
+            "version": "1.8.1",
+            "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+            "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
+            "dev": true
+        },
+        "eventemitter3": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+            "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
+            "dev": true
+        },
+        "events": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz",
+            "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==",
+            "dev": true
+        },
+        "eventsource": {
+            "version": "1.0.7",
+            "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz",
+            "integrity": "sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==",
+            "dev": true,
+            "requires": {
+                "original": "^1.0.0"
+            }
+        },
+        "evp_bytestokey": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+            "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+            "dev": true,
+            "requires": {
+                "md5.js": "^1.3.4",
+                "safe-buffer": "^5.1.1"
+            }
+        },
+        "execa": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
+            "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
+            "dev": true,
+            "requires": {
+                "cross-spawn": "^6.0.0",
+                "get-stream": "^4.0.0",
+                "is-stream": "^1.1.0",
+                "npm-run-path": "^2.0.0",
+                "p-finally": "^1.0.0",
+                "signal-exit": "^3.0.0",
+                "strip-eof": "^1.0.0"
+            },
+            "dependencies": {
+                "cross-spawn": {
+                    "version": "6.0.5",
+                    "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
+                    "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
+                    "dev": true,
+                    "requires": {
+                        "nice-try": "^1.0.4",
+                        "path-key": "^2.0.1",
+                        "semver": "^5.5.0",
+                        "shebang-command": "^1.2.0",
+                        "which": "^1.2.9"
+                    }
+                },
+                "semver": {
+                    "version": "5.7.0",
+                    "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
+                    "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
+                    "dev": true
+                },
+                "which": {
+                    "version": "1.3.1",
+                    "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+                    "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+                    "dev": true,
+                    "requires": {
+                        "isexe": "^2.0.0"
+                    }
+                }
+            }
+        },
+        "execall": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz",
+            "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=",
+            "dev": true,
+            "requires": {
+                "clone-regexp": "^1.0.0"
+            }
+        },
+        "exit": {
+            "version": "0.1.2",
+            "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+            "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=",
+            "dev": true
+        },
+        "expand-brackets": {
+            "version": "2.1.4",
+            "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
+            "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
+            "dev": true,
+            "requires": {
+                "debug": "^2.3.3",
+                "define-property": "^0.2.5",
+                "extend-shallow": "^2.0.1",
+                "posix-character-classes": "^0.1.0",
+                "regex-not": "^1.0.0",
+                "snapdragon": "^0.8.1",
+                "to-regex": "^3.0.1"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "define-property": {
+                    "version": "0.2.5",
+                    "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+                    "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+                    "dev": true,
+                    "requires": {
+                        "is-descriptor": "^0.1.0"
+                    }
+                },
+                "extend-shallow": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "dev": true,
+                    "requires": {
+                        "is-extendable": "^0.1.0"
+                    }
+                }
+            }
+        },
+        "expand-tilde": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
+            "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
+            "dev": true,
+            "requires": {
+                "homedir-polyfill": "^1.0.1"
+            }
+        },
+        "express": {
+            "version": "4.16.4",
+            "resolved": "https://registry.npmjs.org/express/-/express-4.16.4.tgz",
+            "integrity": "sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg==",
+            "dev": true,
+            "requires": {
+                "accepts": "~1.3.5",
+                "array-flatten": "1.1.1",
+                "body-parser": "1.18.3",
+                "content-disposition": "0.5.2",
+                "content-type": "~1.0.4",
+                "cookie": "0.3.1",
+                "cookie-signature": "1.0.6",
+                "debug": "2.6.9",
+                "depd": "~1.1.2",
+                "encodeurl": "~1.0.2",
+                "escape-html": "~1.0.3",
+                "etag": "~1.8.1",
+                "finalhandler": "1.1.1",
+                "fresh": "0.5.2",
+                "merge-descriptors": "1.0.1",
+                "methods": "~1.1.2",
+                "on-finished": "~2.3.0",
+                "parseurl": "~1.3.2",
+                "path-to-regexp": "0.1.7",
+                "proxy-addr": "~2.0.4",
+                "qs": "6.5.2",
+                "range-parser": "~1.2.0",
+                "safe-buffer": "5.1.2",
+                "send": "0.16.2",
+                "serve-static": "1.13.2",
+                "setprototypeof": "1.1.0",
+                "statuses": "~1.4.0",
+                "type-is": "~1.6.16",
+                "utils-merge": "1.0.1",
+                "vary": "~1.1.2"
+            },
+            "dependencies": {
+                "array-flatten": {
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+                    "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+                    "dev": true
+                },
+                "body-parser": {
+                    "version": "1.18.3",
+                    "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz",
+                    "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
+                    "dev": true,
+                    "requires": {
+                        "bytes": "3.0.0",
+                        "content-type": "~1.0.4",
+                        "debug": "2.6.9",
+                        "depd": "~1.1.2",
+                        "http-errors": "~1.6.3",
+                        "iconv-lite": "0.4.23",
+                        "on-finished": "~2.3.0",
+                        "qs": "6.5.2",
+                        "raw-body": "2.3.3",
+                        "type-is": "~1.6.16"
+                    }
+                },
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "finalhandler": {
+                    "version": "1.1.1",
+                    "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+                    "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
+                    "dev": true,
+                    "requires": {
+                        "debug": "2.6.9",
+                        "encodeurl": "~1.0.2",
+                        "escape-html": "~1.0.3",
+                        "on-finished": "~2.3.0",
+                        "parseurl": "~1.3.2",
+                        "statuses": "~1.4.0",
+                        "unpipe": "~1.0.0"
+                    }
+                },
+                "qs": {
+                    "version": "6.5.2",
+                    "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
+                    "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
+                    "dev": true
+                },
+                "raw-body": {
+                    "version": "2.3.3",
+                    "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz",
+                    "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==",
+                    "dev": true,
+                    "requires": {
+                        "bytes": "3.0.0",
+                        "http-errors": "1.6.3",
+                        "iconv-lite": "0.4.23",
+                        "unpipe": "1.0.0"
+                    }
+                },
+                "safe-buffer": {
+                    "version": "5.1.2",
+                    "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+                    "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+                    "dev": true
+                },
+                "statuses": {
+                    "version": "1.4.0",
+                    "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
+                    "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==",
+                    "dev": true
+                }
+            }
+        },
+        "extend": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+            "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+        },
+        "extend-shallow": {
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
+            "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
+            "dev": true,
+            "requires": {
+                "assign-symbols": "^1.0.0",
+                "is-extendable": "^1.0.1"
+            },
+            "dependencies": {
+                "is-extendable": {
+                    "version": "1.0.1",
+                    "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+                    "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+                    "dev": true,
+                    "requires": {
+                        "is-plain-object": "^2.0.4"
+                    }
+                }
+            }
+        },
+        "external-editor": {
+            "version": "3.0.3",
+            "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz",
+            "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==",
+            "dev": true,
+            "requires": {
+                "chardet": "^0.7.0",
+                "iconv-lite": "^0.4.24",
+                "tmp": "^0.0.33"
+            },
+            "dependencies": {
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+                    "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+                    "dev": true,
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                }
+            }
+        },
+        "extglob": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
+            "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+            "dev": true,
+            "requires": {
+                "array-unique": "^0.3.2",
+                "define-property": "^1.0.0",
+                "expand-brackets": "^2.1.4",
+                "extend-shallow": "^2.0.1",
+                "fragment-cache": "^0.2.1",
+                "regex-not": "^1.0.0",
+                "snapdragon": "^0.8.1",
+                "to-regex": "^3.0.1"
+            },
+            "dependencies": {
+                "array-unique": {
+                    "version": "0.3.2",
+                    "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
+                    "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
+                    "dev": true
+                },
+                "define-property": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+                    "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+                    "dev": true,
+                    "requires": {
+                        "is-descriptor": "^1.0.0"
+                    }
+                },
+                "extend-shallow": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "dev": true,
+                    "requires": {
+                        "is-extendable": "^0.1.0"
+                    }
+                },
+                "is-accessor-descriptor": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+                    "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^6.0.0"
+                    }
+                },
+                "is-data-descriptor": {
+                    "version": "1.0.0",
+                    "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+                    "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^6.0.0"
+                    }
+                },
+                "is-descriptor": {
+                    "version": "1.0.2",
+                    "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+                    "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+                    "dev": true,
+                    "requires": {
+                        "is-accessor-descriptor": "^1.0.0",
+                        "is-data-descriptor": "^1.0.0",
+                        "kind-of": "^6.0.2"
+                    }
+                },
+                "kind-of": {
+                    "version": "6.0.2",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
+                    "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
+                    "dev": true
+                }
+            }
+        },
+        "extsprintf": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+            "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
+            "dev": true
+        },
+        "fast-deep-equal": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
+            "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
+            "dev": true
+        },
+        "fast-glob": {
+            "version": "2.2.6",
+            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz",
+            "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==",
+            "dev": true,
+            "requires": {
+                "@mrmlnc/readdir-enhanced": "^2.2.1",
+                "@nodelib/fs.stat": "^1.1.2",
+                "glob-parent": "^3.1.0",
+                "is-glob": "^4.0.0",
+                "merge2": "^1.2.3",
+                "micromatch": "^3.1.10"
+            },
+            "dependencies": {
+                "is-glob": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+                    "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+                    "dev": true,
+                    "requires": {
+                        "is-extglob": "^2.1.1"
+                    }
+                }
+            }
+        },
+        "fast-json-stable-stringify": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
+            "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
+            "dev": true
+        },
+        "fast-levenshtein": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+            "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+            "dev": true
+        },
+        "fastparse": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+            "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+            "dev": true
+        },
+        "faye-websocket": {
+            "version": "0.10.0",
+            "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
+            "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=",
+            "dev": true,
+            "requires": {
+                "websocket-driver": ">=0.5.1"
+            }
+        },
+        "figgy-pudding": {
+            "version": "3.5.1",
+            "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
+            "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==",
+            "dev": true
+        },
+        "figures": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+            "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
+            "dev": true,
+            "requires": {
+                "escape-string-regexp": "^1.0.5"
+            }
+        },
+        "file-entry-cache": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
+            "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+            "dev": true,
+            "requires": {
+                "flat-cache": "^2.0.1"
+            }
+        },
+        "file-loader": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz",
+            "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==",
+            "dev": true,
+            "requires": {
+                "loader-utils": "^1.0.2",
+                "schema-utils": "^1.0.0"
+            }
+        },
+        "fileset": {
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz",
+            "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=",
+            "dev": true,
+            "requires": {
+                "glob": "^7.0.3",
+                "minimatch": "^3.0.3"
+            }
+        },
+        "fill-range": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
+            "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
+            "dev": true,
+            "requires": {
+                "extend-shallow": "^2.0.1",
+                "is-number": "^3.0.0",
+                "repeat-string": "^1.6.1",
+                "to-regex-range": "^2.1.0"
+            },
+            "dependencies": {
+                "extend-shallow": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+                    "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+                    "dev": true,
+                    "requires": {
+                        "is-extendable": "^0.1.0"
+                    }
+                }
+            }
+        },
+        "finalhandler": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
+            "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
+            "dev": true,
+            "requires": {
+                "debug": "2.6.9",
+                "encodeurl": "~1.0.2",
+                "escape-html": "~1.0.3",
+                "on-finished": "~2.3.0",
+                "parseurl": "~1.3.3",
+                "statuses": "~1.5.0",
+                "unpipe": "~1.0.0"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "2.6.9",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                    "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "2.0.0"
+                    }
+                },
+                "parseurl": {
+                    "version": "1.3.3",
+                    "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+                    "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+                    "dev": true
+                }
+            }
+        },
+        "find-cache-dir": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+            "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+            "dev": true,
+            "requires": {
+                "commondir": "^1.0.1",
+                "make-dir": "^2.0.0",
+                "pkg-dir": "^3.0.0"
+            }
+        },
+        "find-parent-dir": {
+            "version": "0.3.0",
+            "resolved": "https://registry.npmjs.org/find-parent-dir/-/find-parent-dir-0.3.0.tgz",
+            "integrity": "sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ=",
+            "dev": true
+        },
+        "find-up": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
+            "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
+            "dev": true,
+            "requires": {
+                "path-exists": "^2.0.0",
+                "pinkie-promise": "^2.0.0"
+            }
+        },
+        "findup-sync": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
+            "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
+            "dev": true,
+            "requires": {
+                "detect-file": "^1.0.0",
+                "is-glob": "^3.1.0",
+                "micromatch": "^3.0.4",
+                "resolve-dir": "^1.0.1"
+            }
+        },
+        "flat-cache": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
+            "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
+            "dev": true,
+            "requires": {
+                "flatted": "^2.0.0",
+                "rimraf": "2.6.3",
+                "write": "1.0.3"
+            },
+            "dependencies": {
+                "rimraf": {
+                    "version": "2.6.3",
+                    "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
+                    "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
+                    "dev": true,
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                }
+            }
+        },
+        "flatted": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.0.tgz",
+            "integrity": "sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg==",
+            "dev": true
+        },
+        "flush-write-stream": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
+            "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.3",
+                "readable-stream": "^2.3.6"
+            }
+        },
+        "fn-name": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz",
+            "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=",
+            "dev": true
+        },
+        "follow-redirects": {
+            "version": "1.7.0",
+            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.7.0.tgz",
+            "integrity": "sha512-m/pZQy4Gj287eNy94nivy5wchN3Kp+Q5WgUPNy5lJSZ3sgkVKSYV/ZChMAQVIgx1SqfZ2zBZtPA2YlXIWxxJOQ==",
+            "dev": true,
+            "requires": {
+                "debug": "^3.2.6"
+            },
+            "dependencies": {
+                "debug": {
+                    "version": "3.2.6",
+                    "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+                    "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+                    "dev": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
+                },
+                "ms": {
+                    "version": "2.1.1",
+                    "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+                    "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
+                    "dev": true
+                }
+            }
+        },
+        "font-awesome": {
+            "version": "4.7.0",
+            "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz",
+            "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM="
+        },
+        "for-in": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+            "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+            "dev": true
+        },
+        "for-own": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
+            "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
+            "dev": true,
+            "requires": {
+                "for-in": "^1.0.1"
+            }
+        },
+        "forever-agent": {
+            "version": "0.6.1",
+            "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+            "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
+            "dev": true
+        },
+        "form-data": {
+            "version": "2.3.2",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
+            "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
+            "requires": {
+                "asynckit": "^0.4.0",
+                "combined-stream": "1.0.6",
+                "mime-types": "^2.1.12"
+            }
         },
-        "json5": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
-          "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
-          "dev": true,
-          "requires": {
-            "minimist": "1.2.0"
-          }
+        "formidable": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
+            "integrity": "sha1-cPt8oCkO5v+WEJBBX0s989IIJlk="
+        },
+        "forwarded": {
+            "version": "0.1.2",
+            "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
+            "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
+            "dev": true
+        },
+        "fragment-cache": {
+            "version": "0.2.1",
+            "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
+            "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
+            "dev": true,
+            "requires": {
+                "map-cache": "^0.2.2"
+            }
         },
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
+        "fresh": {
+            "version": "0.5.2",
+            "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+            "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+            "dev": true
+        },
+        "from2": {
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+            "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.1",
+                "readable-stream": "^2.0.0"
+            }
         },
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
+        "fs-access": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz",
+            "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=",
+            "dev": true,
+            "requires": {
+                "null-check": "^1.0.0"
+            }
         },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
-          "dev": true
+        "fs-extra": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+            "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+            "dev": true,
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "jsonfile": "^4.0.0",
+                "universalify": "^0.1.0"
+            }
         },
-        "resolve": {
-          "version": "1.10.1",
-          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.1.tgz",
-          "integrity": "sha512-KuIe4mf++td/eFb6wkaPbMDnP6kObCaEtIDuHOUED6MNUo4K670KZUHuuvYPZDxNF0WVLw49n06M2m2dXphEzA==",
-          "dev": true,
-          "requires": {
-            "path-parse": "1.0.6"
-          }
+        "fs-write-stream-atomic": {
+            "version": "1.0.10",
+            "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
+            "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=",
+            "dev": true,
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "iferr": "^0.1.5",
+                "imurmurhash": "^0.1.4",
+                "readable-stream": "1 || 2"
+            }
         },
-        "semver": {
-          "version": "5.7.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
-          "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
-          "dev": true
+        "fs.realpath": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+            "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+            "dev": true
+        },
+        "fsevents": {
+            "version": "1.2.9",
+            "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz",
+            "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==",
+            "dev": true,
+            "optional": true,
+            "requires": {
+                "nan": "^2.12.1",
+                "node-pre-gyp": "^0.12.0"
+            },
+            "dependencies": {
+                "abbrev": {
+                    "version": "1.1.1",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true
+                },
+                "ansi-regex": {
+                    "version": "2.1.1",
+                    "bundled": true
+                },
+                "aproba": {
+                    "version": "1.2.0",
+                    "bundled": true
+                },
+                "are-we-there-yet": {
+                    "version": "1.1.5",
+                    "bundled": true,
+                    "requires": {
+                        "delegates": "^1.0.0",
+                        "readable-stream": "^2.0.6"
+                    },
+                    "dependencies": {
+                        "process-nextick-args": {
+                            "version": "1.0.7",
+                            "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+                            "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
+                        },
+                        "readable-stream": {
+                            "version": "2.0.6",
+                            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+                            "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+                            "requires": {
+                                "core-util-is": "~1.0.0",
+                                "inherits": "~2.0.1",
+                                "isarray": "~1.0.0",
+                                "process-nextick-args": "~1.0.6",
+                                "string_decoder": "~0.10.x",
+                                "util-deprecate": "~1.0.1"
+                            }
+                        },
+                        "string_decoder": {
+                            "version": "0.10.31",
+                            "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+                            "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
+                        }
+                    }
+                },
+                "balanced-match": {
+                    "version": "1.0.0",
+                    "bundled": true
+                },
+                "brace-expansion": {
+                    "version": "1.1.11",
+                    "bundled": true,
+                    "requires": {
+                        "balanced-match": "^1.0.0",
+                        "concat-map": "0.0.1"
+                    }
+                },
+                "chownr": {
+                    "version": "1.1.1",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true
+                },
+                "code-point-at": {
+                    "version": "1.1.0",
+                    "bundled": true
+                },
+                "concat-map": {
+                    "version": "0.0.1",
+                    "bundled": true
+                },
+                "console-control-strings": {
+                    "version": "1.1.0",
+                    "bundled": true
+                },
+                "core-util-is": {
+                    "version": "1.0.2",
+                    "bundled": true
+                },
+                "debug": {
+                    "version": "4.1.1",
+                    "bundled": true,
+                    "requires": {
+                        "ms": "^2.1.1"
+                    }
+                },
+                "deep-extend": {
+                    "version": "0.6.0",
+                    "bundled": true
+                },
+                "delegates": {
+                    "version": "1.0.0",
+                    "bundled": true
+                },
+                "detect-libc": {
+                    "version": "1.0.3",
+                    "bundled": true
+                },
+                "fs-minipass": {
+                    "version": "1.2.5",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "minipass": "^2.2.1"
+                    },
+                    "dependencies": {
+                        "minipass": {
+                            "version": "2.2.1",
+                            "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz",
+                            "integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "yallist": "^3.0.0"
+                            }
+                        }
+                    }
+                },
+                "fs.realpath": {
+                    "version": "1.0.0",
+                    "bundled": true
+                },
+                "gauge": {
+                    "version": "2.7.4",
+                    "bundled": true,
+                    "requires": {
+                        "aproba": "^1.0.3",
+                        "console-control-strings": "^1.0.0",
+                        "has-unicode": "^2.0.0",
+                        "object-assign": "^4.1.0",
+                        "signal-exit": "^3.0.0",
+                        "string-width": "^1.0.1",
+                        "strip-ansi": "^3.0.1",
+                        "wide-align": "^1.1.0"
+                    },
+                    "dependencies": {
+                        "aproba": {
+                            "version": "1.0.3",
+                            "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.0.3.tgz",
+                            "integrity": "sha1-f7baOnLHAknbY/2bXGSzGvcYqU8="
+                        },
+                        "console-control-strings": {
+                            "version": "1.0.0",
+                            "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.0.0.tgz",
+                            "integrity": "sha1-TmqsJURKsVf1KKRIfWUkolxQak8="
+                        },
+                        "has-unicode": {
+                            "version": "2.0.0",
+                            "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.0.tgz",
+                            "integrity": "sha1-o82Wwwe6QdVZxaLuQIwSoRxMLsM="
+                        },
+                        "object-assign": {
+                            "version": "4.1.0",
+                            "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz",
+                            "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A="
+                        },
+                        "signal-exit": {
+                            "version": "3.0.0",
+                            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.0.tgz",
+                            "integrity": "sha1-PAVDtl17T7xgts2UWT2b9DZzm+g="
+                        },
+                        "string-width": {
+                            "version": "1.0.1",
+                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.1.tgz",
+                            "integrity": "sha1-ySEptvHX9SrPmvQkom44ZKBc6wo=",
+                            "requires": {
+                                "code-point-at": "^1.0.0",
+                                "is-fullwidth-code-point": "^1.0.0",
+                                "strip-ansi": "^3.0.0"
+                            }
+                        },
+                        "wide-align": {
+                            "version": "1.1.0",
+                            "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz",
+                            "integrity": "sha1-QO3egCpx/qHwcNo+YtzaLnrdlq0=",
+                            "requires": {
+                                "string-width": "^1.0.1"
+                            }
+                        }
+                    }
+                },
+                "glob": {
+                    "version": "7.1.3",
+                    "bundled": true,
+                    "requires": {
+                        "fs.realpath": "^1.0.0",
+                        "inflight": "^1.0.4",
+                        "inherits": "2",
+                        "minimatch": "^3.0.4",
+                        "once": "^1.3.0",
+                        "path-is-absolute": "^1.0.0"
+                    },
+                    "dependencies": {
+                        "inflight": {
+                            "version": "1.0.4",
+                            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.4.tgz",
+                            "integrity": "sha1-bLtFIevVHODsCpNr/XZX736bFyo=",
+                            "requires": {
+                                "once": "^1.3.0",
+                                "wrappy": "1"
+                            }
+                        },
+                        "once": {
+                            "version": "1.3.0",
+                            "resolved": "https://registry.npmjs.org/once/-/once-1.3.0.tgz",
+                            "integrity": "sha1-FRr4a/wfCMS58H0GqyUP/L61ZYE="
+                        },
+                        "path-is-absolute": {
+                            "version": "1.0.0",
+                            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz",
+                            "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI="
+                        }
+                    }
+                },
+                "has-unicode": {
+                    "version": "2.0.1",
+                    "bundled": true
+                },
+                "iconv-lite": {
+                    "version": "0.4.24",
+                    "bundled": true,
+                    "requires": {
+                        "safer-buffer": ">= 2.1.2 < 3"
+                    }
+                },
+                "ignore-walk": {
+                    "version": "3.0.1",
+                    "bundled": true,
+                    "requires": {
+                        "minimatch": "^3.0.4"
+                    }
+                },
+                "inflight": {
+                    "version": "1.0.6",
+                    "bundled": true,
+                    "requires": {
+                        "once": "^1.3.0",
+                        "wrappy": "1"
+                    }
+                },
+                "inherits": {
+                    "version": "2.0.3",
+                    "bundled": true
+                },
+                "ini": {
+                    "version": "1.3.5",
+                    "bundled": true
+                },
+                "is-fullwidth-code-point": {
+                    "version": "1.0.0",
+                    "bundled": true,
+                    "requires": {
+                        "number-is-nan": "^1.0.0"
+                    },
+                    "dependencies": {
+                        "number-is-nan": {
+                            "version": "1.0.0",
+                            "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.0.tgz",
+                            "integrity": "sha1-wCD1KcUoKt/dIz2R1LGBw9aG3Es="
+                        }
+                    }
+                },
+                "isarray": {
+                    "version": "1.0.0",
+                    "bundled": true
+                },
+                "minimatch": {
+                    "version": "3.0.4",
+                    "bundled": true,
+                    "requires": {
+                        "brace-expansion": "^1.1.7"
+                    },
+                    "dependencies": {
+                        "balanced-match": {
+                            "version": "0.4.2",
+                            "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz",
+                            "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg="
+                        },
+                        "brace-expansion": {
+                            "version": "1.1.7",
+                            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.7.tgz",
+                            "integrity": "sha1-Pv/DxQ4ABTH7cg6v+A8K6O8jz1k=",
+                            "requires": {
+                                "balanced-match": "^0.4.1",
+                                "concat-map": "0.0.1"
+                            }
+                        }
+                    }
+                },
+                "minimist": {
+                    "version": "0.0.8",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true
+                },
+                "minipass": {
+                    "version": "2.3.5",
+                    "bundled": true,
+                    "requires": {
+                        "safe-buffer": "^5.1.2",
+                        "yallist": "^3.0.0"
+                    }
+                },
+                "minizlib": {
+                    "version": "1.2.1",
+                    "bundled": true,
+                    "requires": {
+                        "minipass": "^2.2.1"
+                    }
+                },
+                "mkdirp": {
+                    "version": "0.5.1",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "minimist": "0.0.8"
+                    }
+                },
+                "ms": {
+                    "version": "2.1.1",
+                    "bundled": true
+                },
+                "nan": {
+                    "version": "2.13.2",
+                    "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
+                    "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
+                    "dev": true,
+                    "optional": true
+                },
+                "needle": {
+                    "version": "2.3.0",
+                    "bundled": true,
+                    "requires": {
+                        "debug": "^4.1.0",
+                        "iconv-lite": "^0.4.4",
+                        "sax": "^1.2.4"
+                    }
+                },
+                "node-pre-gyp": {
+                    "version": "0.12.0",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "detect-libc": "^1.0.2",
+                        "mkdirp": "^0.5.1",
+                        "needle": "^2.2.1",
+                        "nopt": "^4.0.1",
+                        "npm-packlist": "^1.1.6",
+                        "npmlog": "^4.0.2",
+                        "rc": "^1.2.7",
+                        "rimraf": "^2.6.1",
+                        "semver": "^5.3.0",
+                        "tar": "^4"
+                    },
+                    "dependencies": {
+                        "debug": {
+                            "version": "2.6.9",
+                            "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+                            "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "ms": "2.0.0"
+                            }
+                        },
+                        "deep-extend": {
+                            "version": "0.5.1",
+                            "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz",
+                            "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==",
+                            "dev": true,
+                            "optional": true
+                        },
+                        "detect-libc": {
+                            "version": "1.0.2",
+                            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.2.tgz",
+                            "integrity": "sha1-ca1dIEvxempsqPRQxhRUBm70YeE=",
+                            "dev": true,
+                            "optional": true
+                        },
+                        "minimist": {
+                            "version": "1.2.0",
+                            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+                            "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+                            "dev": true,
+                            "optional": true
+                        },
+                        "ms": {
+                            "version": "2.0.0",
+                            "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+                            "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+                            "dev": true,
+                            "optional": true
+                        },
+                        "needle": {
+                            "version": "2.2.1",
+                            "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.1.tgz",
+                            "integrity": "sha512-t/ZswCM9JTWjAdXS9VpvqhI2Ct2sL2MdY4fUXqGJaGBk13ge99ObqRksRTbBE56K+wxUXwwfZYOuZHifFW9q+Q==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "debug": "^2.1.2",
+                                "iconv-lite": "^0.4.4",
+                                "sax": "^1.2.4"
+                            }
+                        },
+                        "npm-packlist": {
+                            "version": "1.1.6",
+                            "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.6.tgz",
+                            "integrity": "sha512-M6hwEInQcyFuIyk2jwNkTEQqD57Qd9B117EZLwi/aI3s7vyDhd1tRXYbi/xEekhZkUUly5YapArLHdfrDrxuUg==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "ignore-walk": "^3.0.0",
+                                "npm-bundled": "^1.0.1"
+                            }
+                        },
+                        "npmlog": {
+                            "version": "4.0.2",
+                            "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.0.2.tgz",
+                            "integrity": "sha1-0DlQ4OeM4VJ7om0qdZLpNIrD518=",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "are-we-there-yet": "~1.1.2",
+                                "console-control-strings": "~1.1.0",
+                                "gauge": "~2.7.1",
+                                "set-blocking": "~2.0.0"
+                            }
+                        },
+                        "rc": {
+                            "version": "1.2.7",
+                            "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz",
+                            "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "deep-extend": "^0.5.1",
+                                "ini": "~1.3.0",
+                                "minimist": "^1.2.0",
+                                "strip-json-comments": "~2.0.1"
+                            }
+                        },
+                        "rimraf": {
+                            "version": "2.6.1",
+                            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+                            "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "glob": "^7.0.5"
+                            }
+                        },
+                        "semver": {
+                            "version": "5.3.0",
+                            "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+                            "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
+                            "dev": true,
+                            "optional": true
+                        }
+                    }
+                },
+                "nopt": {
+                    "version": "4.0.1",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "abbrev": "1",
+                        "osenv": "^0.1.4"
+                    },
+                    "dependencies": {
+                        "osenv": {
+                            "version": "0.1.4",
+                            "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
+                            "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "os-homedir": "^1.0.0",
+                                "os-tmpdir": "^1.0.0"
+                            }
+                        }
+                    }
+                },
+                "npm-bundled": {
+                    "version": "1.0.6",
+                    "bundled": true
+                },
+                "npm-packlist": {
+                    "version": "1.4.1",
+                    "bundled": true,
+                    "requires": {
+                        "ignore-walk": "^3.0.1",
+                        "npm-bundled": "^1.0.1"
+                    }
+                },
+                "npmlog": {
+                    "version": "4.1.2",
+                    "bundled": true,
+                    "requires": {
+                        "are-we-there-yet": "~1.1.2",
+                        "console-control-strings": "~1.1.0",
+                        "gauge": "~2.7.3",
+                        "set-blocking": "~2.0.0"
+                    }
+                },
+                "number-is-nan": {
+                    "version": "1.0.1",
+                    "bundled": true
+                },
+                "object-assign": {
+                    "version": "4.1.1",
+                    "bundled": true
+                },
+                "once": {
+                    "version": "1.4.0",
+                    "bundled": true,
+                    "requires": {
+                        "wrappy": "1"
+                    }
+                },
+                "os-homedir": {
+                    "version": "1.0.2",
+                    "bundled": true
+                },
+                "os-tmpdir": {
+                    "version": "1.0.2",
+                    "bundled": true
+                },
+                "osenv": {
+                    "version": "0.1.5",
+                    "bundled": true,
+                    "requires": {
+                        "os-homedir": "^1.0.0",
+                        "os-tmpdir": "^1.0.0"
+                    }
+                },
+                "path-is-absolute": {
+                    "version": "1.0.1",
+                    "bundled": true
+                },
+                "process-nextick-args": {
+                    "version": "2.0.0",
+                    "bundled": true
+                },
+                "rc": {
+                    "version": "1.2.8",
+                    "bundled": true,
+                    "requires": {
+                        "deep-extend": "^0.6.0",
+                        "ini": "~1.3.0",
+                        "minimist": "^1.2.0",
+                        "strip-json-comments": "~2.0.1"
+                    },
+                    "dependencies": {
+                        "minimist": {
+                            "version": "1.2.0",
+                            "bundled": true
+                        }
+                    }
+                },
+                "readable-stream": {
+                    "version": "2.3.6",
+                    "bundled": true,
+                    "requires": {
+                        "core-util-is": "~1.0.0",
+                        "inherits": "~2.0.3",
+                        "isarray": "~1.0.0",
+                        "process-nextick-args": "~2.0.0",
+                        "safe-buffer": "~5.1.1",
+                        "string_decoder": "~1.1.1",
+                        "util-deprecate": "~1.0.1"
+                    }
+                },
+                "rimraf": {
+                    "version": "2.6.3",
+                    "bundled": true,
+                    "requires": {
+                        "glob": "^7.1.3"
+                    }
+                },
+                "safe-buffer": {
+                    "version": "5.1.2",
+                    "bundled": true
+                },
+                "safer-buffer": {
+                    "version": "2.1.2",
+                    "bundled": true
+                },
+                "sax": {
+                    "version": "1.2.4",
+                    "bundled": true
+                },
+                "semver": {
+                    "version": "5.7.0",
+                    "bundled": true
+                },
+                "set-blocking": {
+                    "version": "2.0.0",
+                    "bundled": true
+                },
+                "signal-exit": {
+                    "version": "3.0.2",
+                    "bundled": true
+                },
+                "string-width": {
+                    "version": "1.0.2",
+                    "bundled": true,
+                    "requires": {
+                        "code-point-at": "^1.0.0",
+                        "is-fullwidth-code-point": "^1.0.0",
+                        "strip-ansi": "^3.0.0"
+                    }
+                },
+                "string_decoder": {
+                    "version": "1.1.1",
+                    "bundled": true,
+                    "requires": {
+                        "safe-buffer": "~5.1.0"
+                    }
+                },
+                "strip-ansi": {
+                    "version": "3.0.1",
+                    "bundled": true,
+                    "requires": {
+                        "ansi-regex": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "ansi-regex": {
+                            "version": "2.0.0",
+                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz",
+                            "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc="
+                        }
+                    }
+                },
+                "strip-json-comments": {
+                    "version": "2.0.1",
+                    "bundled": true
+                },
+                "tar": {
+                    "version": "4.4.8",
+                    "bundled": true,
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "chownr": "^1.1.1",
+                        "fs-minipass": "^1.2.5",
+                        "minipass": "^2.3.4",
+                        "minizlib": "^1.1.1",
+                        "mkdirp": "^0.5.0",
+                        "safe-buffer": "^5.1.2",
+                        "yallist": "^3.0.2"
+                    },
+                    "dependencies": {
+                        "minipass": {
+                            "version": "2.3.4",
+                            "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.4.tgz",
+                            "integrity": "sha512-mlouk1OHlaUE8Odt1drMtG1bAJA4ZA6B/ehysgV0LUIrDHdKgo1KorZq3pK0b/7Z7LJIQ12MNM6aC+Tn6lUZ5w==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "safe-buffer": "^5.1.2",
+                                "yallist": "^3.0.0"
+                            }
+                        },
+                        "minizlib": {
+                            "version": "1.1.1",
+                            "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz",
+                            "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "minipass": "^2.2.1"
+                            }
+                        },
+                        "mkdirp": {
+                            "version": "0.5.0",
+                            "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz",
+                            "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=",
+                            "dev": true,
+                            "optional": true,
+                            "requires": {
+                                "minimist": "0.0.8"
+                            }
+                        },
+                        "yallist": {
+                            "version": "3.0.2",
+                            "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz",
+                            "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=",
+                            "dev": true,
+                            "optional": true
+                        }
+                    }
+                },
+                "util-deprecate": {
+                    "version": "1.0.2",
+                    "bundled": true
+                },
+                "wide-align": {
+                    "version": "1.1.3",
+                    "bundled": true,
+                    "requires": {
+                        "string-width": "^1.0.2 || 2"
+                    }
+                },
+                "wrappy": {
+                    "version": "1.0.2",
+                    "bundled": true
+                },
+                "yallist": {
+                    "version": "3.0.3",
+                    "bundled": true
+                }
+            }
         },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
-      }
-    },
-    "@babel/generator": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.4.4.tgz",
-      "integrity": "sha512-53UOLK6TVNqKxf7RUh8NE851EHRxOOeVXKbK2bivdb+iziMyk03Sr4eaE9OELCbyZAAafAKPDwF2TPUES5QbxQ==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4",
-        "jsesc": "2.5.2",
-        "lodash": "4.17.15",
-        "source-map": "0.5.7",
-        "trim-right": "1.0.1"
-      },
-      "dependencies": {
-        "jsesc": {
-          "version": "2.5.2",
-          "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
-          "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
-          "dev": true
+        "fstream": {
+            "version": "1.0.12",
+            "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
+            "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
+            "dev": true,
+            "requires": {
+                "graceful-fs": "^4.1.2",
+                "inherits": "~2.0.0",
+                "mkdirp": ">=0.5 0",
+                "rimraf": "2"
+            }
         },
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
+        "function-bind": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+            "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+            "dev": true
+        },
+        "functional-red-black-tree": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+            "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
+            "dev": true
+        },
+        "g-status": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/g-status/-/g-status-2.0.2.tgz",
+            "integrity": "sha512-kQoE9qH+T1AHKgSSD0Hkv98bobE90ILQcXAF4wvGgsr7uFqNvwmh8j+Lq3l0RVt3E3HjSbv2B9biEGcEtpHLCA==",
+            "dev": true,
+            "requires": {
+                "arrify": "^1.0.1",
+                "matcher": "^1.0.0",
+                "simple-git": "^1.85.0"
+            }
         },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
-      }
-    },
-    "@babel/helper-annotate-as-pure": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz",
-      "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-builder-binary-assignment-operator-visitor": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz",
-      "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-explode-assignable-expression": "7.1.0",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-call-delegate": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz",
-      "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-hoist-variables": "7.4.4",
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-define-map": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.4.4.tgz",
-      "integrity": "sha512-IX3Ln8gLhZpSuqHJSnTNBWGDE9kdkTEWl21A/K7PQ00tseBwbqCHTvNLHSBd9M0R5rER4h5Rsvj9vw0R5SieBg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-function-name": "7.1.0",
-        "@babel/types": "7.4.4",
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/helper-explode-assignable-expression": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz",
-      "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==",
-      "dev": true,
-      "requires": {
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-function-name": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz",
-      "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-get-function-arity": "7.0.0",
-        "@babel/template": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-get-function-arity": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz",
-      "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-hoist-variables": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz",
-      "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-member-expression-to-functions": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.0.0.tgz",
-      "integrity": "sha512-avo+lm/QmZlv27Zsi0xEor2fKcqWG56D5ae9dzklpIaY7cQMK5N8VSpaNVPPagiqmy7LrEjK1IWdGMOqPu5csg==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-module-imports": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz",
-      "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-module-transforms": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.4.4.tgz",
-      "integrity": "sha512-3Z1yp8TVQf+B4ynN7WoHPKS8EkdTbgAEy0nU0rs/1Kw4pDgmvYH3rz3aI11KgxKCba2cn7N+tqzV1mY2HMN96w==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-imports": "7.0.0",
-        "@babel/helper-simple-access": "7.1.0",
-        "@babel/helper-split-export-declaration": "7.4.4",
-        "@babel/template": "7.4.4",
-        "@babel/types": "7.4.4",
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/helper-optimise-call-expression": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz",
-      "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-plugin-utils": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz",
-      "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==",
-      "dev": true
-    },
-    "@babel/helper-regex": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.4.4.tgz",
-      "integrity": "sha512-Y5nuB/kESmR3tKjU8Nkn1wMGEx1tjJX076HBMeL3XLQCu6vA/YRzuTW0bbb+qRnXvQGn+d6Rx953yffl8vEy7Q==",
-      "dev": true,
-      "requires": {
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/helper-remap-async-to-generator": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz",
-      "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-annotate-as-pure": "7.0.0",
-        "@babel/helper-wrap-function": "7.2.0",
-        "@babel/template": "7.4.4",
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-replace-supers": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.4.4.tgz",
-      "integrity": "sha512-04xGEnd+s01nY1l15EuMS1rfKktNF+1CkKmHoErDppjAAZL+IUBZpzT748x262HF7fibaQPhbvWUl5HeSt1EXg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-member-expression-to-functions": "7.0.0",
-        "@babel/helper-optimise-call-expression": "7.0.0",
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-simple-access": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz",
-      "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==",
-      "dev": true,
-      "requires": {
-        "@babel/template": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-split-export-declaration": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz",
-      "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==",
-      "dev": true,
-      "requires": {
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helper-wrap-function": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz",
-      "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-function-name": "7.1.0",
-        "@babel/template": "7.4.4",
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/helpers": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.4.4.tgz",
-      "integrity": "sha512-igczbR/0SeuPR8RFfC7tGrbdTbFL3QTvH6D+Z6zNxnTe//GyqmtHmDkzrqDmyZ3eSwPqB/LhyKoU5DXsp+Vp2A==",
-      "dev": true,
-      "requires": {
-        "@babel/template": "7.4.4",
-        "@babel/traverse": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/highlight": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz",
-      "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==",
-      "dev": true,
-      "requires": {
-        "chalk": "2.4.2",
-        "esutils": "2.0.2",
-        "js-tokens": "4.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "3.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-          "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-          "dev": true,
-          "requires": {
-            "color-convert": "1.9.2"
-          }
+        "gauge": {
+            "version": "2.7.4",
+            "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
+            "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+            "dev": true,
+            "requires": {
+                "aproba": "^1.0.3",
+                "console-control-strings": "^1.0.0",
+                "has-unicode": "^2.0.0",
+                "object-assign": "^4.1.0",
+                "signal-exit": "^3.0.0",
+                "string-width": "^1.0.1",
+                "strip-ansi": "^3.0.1",
+                "wide-align": "^1.1.0"
+            }
         },
-        "chalk": {
-          "version": "2.4.2",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-          "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "3.2.1",
-            "escape-string-regexp": "1.0.5",
-            "supports-color": "5.5.0"
-          }
+        "gaze": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
+            "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
+            "dev": true,
+            "requires": {
+                "globule": "^1.0.0"
+            }
         },
-        "has-flag": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-          "dev": true
+        "get-caller-file": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
+            "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
+            "dev": true
         },
-        "js-tokens": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-          "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-          "dev": true
+        "get-own-enumerable-property-symbols": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz",
+            "integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg==",
+            "dev": true
         },
-        "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-          "dev": true,
-          "requires": {
-            "has-flag": "3.0.0"
-          }
-        }
-      }
-    },
-    "@babel/parser": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.4.4.tgz",
-      "integrity": "sha512-5pCS4mOsL+ANsFZGdvNLybx4wtqAZJ0MJjMHxvzI3bvIsz6sQvzW8XX92EYIkiPtIvcfG3Aj+Ir5VNyjnZhP7w==",
-      "dev": true
-    },
-    "@babel/plugin-proposal-async-generator-functions": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz",
-      "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-remap-async-to-generator": "7.1.0",
-        "@babel/plugin-syntax-async-generators": "7.2.0"
-      }
-    },
-    "@babel/plugin-proposal-json-strings": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz",
-      "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/plugin-syntax-json-strings": "7.2.0"
-      }
-    },
-    "@babel/plugin-proposal-object-rest-spread": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.4.4.tgz",
-      "integrity": "sha512-dMBG6cSPBbHeEBdFXeQ2QLc5gUpg4Vkaz8octD4aoW/ISO+jBOcsuxYL7bsb5WSu8RLP6boxrBIALEHgoHtO9g==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/plugin-syntax-object-rest-spread": "7.2.0"
-      }
-    },
-    "@babel/plugin-proposal-optional-catch-binding": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz",
-      "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/plugin-syntax-optional-catch-binding": "7.2.0"
-      }
-    },
-    "@babel/plugin-proposal-unicode-property-regex": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz",
-      "integrity": "sha512-j1NwnOqMG9mFUOH58JTFsA/+ZYzQLUZ/drqWUqxCYLGeu2JFZL8YrNC9hBxKmWtAuOCHPcRpgv7fhap09Fb4kA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-regex": "7.4.4",
-        "regexpu-core": "4.5.4"
-      }
-    },
-    "@babel/plugin-syntax-async-generators": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz",
-      "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-syntax-json-strings": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz",
-      "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-syntax-object-rest-spread": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz",
-      "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-syntax-optional-catch-binding": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz",
-      "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-arrow-functions": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz",
-      "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-async-to-generator": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.4.4.tgz",
-      "integrity": "sha512-YiqW2Li8TXmzgbXw+STsSqPBPFnGviiaSp6CYOq55X8GQ2SGVLrXB6pNid8HkqkZAzOH6knbai3snhP7v0fNwA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-imports": "7.0.0",
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-remap-async-to-generator": "7.1.0"
-      }
-    },
-    "@babel/plugin-transform-block-scoped-functions": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz",
-      "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-block-scoping": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.4.4.tgz",
-      "integrity": "sha512-jkTUyWZcTrwxu5DD4rWz6rDB5Cjdmgz6z7M7RLXOJyCUkFBawssDGcGh8M/0FTSB87avyJI1HsTwUXp9nKA1PA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/plugin-transform-classes": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.4.4.tgz",
-      "integrity": "sha512-/e44eFLImEGIpL9qPxSRat13I5QNRgBLu2hOQJCF7VLy/otSM/sypV1+XaIw5+502RX/+6YaSAPmldk+nhHDPw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-annotate-as-pure": "7.0.0",
-        "@babel/helper-define-map": "7.4.4",
-        "@babel/helper-function-name": "7.1.0",
-        "@babel/helper-optimise-call-expression": "7.0.0",
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-replace-supers": "7.4.4",
-        "@babel/helper-split-export-declaration": "7.4.4",
-        "globals": "11.12.0"
-      },
-      "dependencies": {
-        "globals": {
-          "version": "11.12.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/plugin-transform-computed-properties": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz",
-      "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-destructuring": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.4.4.tgz",
-      "integrity": "sha512-/aOx+nW0w8eHiEHm+BTERB2oJn5D127iye/SUQl7NjHy0lf+j7h4MKMMSOwdazGq9OxgiNADncE+SRJkCxjZpQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-dotall-regex": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz",
-      "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-regex": "7.4.4",
-        "regexpu-core": "4.5.4"
-      }
-    },
-    "@babel/plugin-transform-duplicate-keys": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.2.0.tgz",
-      "integrity": "sha512-q+yuxW4DsTjNceUiTzK0L+AfQ0zD9rWaTLiUqHA8p0gxx7lu1EylenfzjeIWNkPy6e/0VG/Wjw9uf9LueQwLOw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-exponentiation-operator": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz",
-      "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-builder-binary-assignment-operator-visitor": "7.1.0",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-for-of": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz",
-      "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-function-name": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz",
-      "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-function-name": "7.1.0",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-literals": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz",
-      "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-member-expression-literals": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz",
-      "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-modules-amd": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.2.0.tgz",
-      "integrity": "sha512-mK2A8ucqz1qhrdqjS9VMIDfIvvT2thrEsIQzbaTdc5QFzhDjQv2CkJJ5f6BXIkgbmaoax3zBr2RyvV/8zeoUZw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-transforms": "7.4.4",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-modules-commonjs": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.4.4.tgz",
-      "integrity": "sha512-4sfBOJt58sEo9a2BQXnZq+Q3ZTSAUXyK3E30o36BOGnJ+tvJ6YSxF0PG6kERvbeISgProodWuI9UVG3/FMY6iw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-transforms": "7.4.4",
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-simple-access": "7.1.0"
-      }
-    },
-    "@babel/plugin-transform-modules-systemjs": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.4.4.tgz",
-      "integrity": "sha512-MSiModfILQc3/oqnG7NrP1jHaSPryO6tA2kOMmAQApz5dayPxWiHqmq4sWH2xF5LcQK56LlbKByCd8Aah/OIkQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-hoist-variables": "7.4.4",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-modules-umd": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.2.0.tgz",
-      "integrity": "sha512-BV3bw6MyUH1iIsGhXlOK6sXhmSarZjtJ/vMiD9dNmpY8QXFFQTj+6v92pcfy1iqa8DeAfJFwoxcrS/TUZda6sw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-transforms": "7.4.4",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-named-capturing-groups-regex": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.4.4.tgz",
-      "integrity": "sha512-Ki+Y9nXBlKfhD+LXaRS7v95TtTGYRAf9Y1rTDiE75zf8YQz4GDaWRXosMfJBXxnk88mGFjWdCRIeqDbon7spYA==",
-      "dev": true,
-      "requires": {
-        "regexp-tree": "0.1.6"
-      }
-    },
-    "@babel/plugin-transform-new-target": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz",
-      "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-object-super": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.2.0.tgz",
-      "integrity": "sha512-VMyhPYZISFZAqAPVkiYb7dUe2AsVi2/wCT5+wZdsNO31FojQJa9ns40hzZ6U9f50Jlq4w6qwzdBB2uwqZ00ebg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-replace-supers": "7.4.4"
-      }
-    },
-    "@babel/plugin-transform-parameters": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz",
-      "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-call-delegate": "7.4.4",
-        "@babel/helper-get-function-arity": "7.0.0",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-property-literals": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz",
-      "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-regenerator": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.4.tgz",
-      "integrity": "sha512-Zz3w+pX1SI0KMIiqshFZkwnVGUhDZzpX2vtPzfJBKQQq8WsP/Xy9DNdELWivxcKOCX/Pywge4SiEaPaLtoDT4g==",
-      "dev": true,
-      "requires": {
-        "regenerator-transform": "0.13.4"
-      }
-    },
-    "@babel/plugin-transform-reserved-words": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz",
-      "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-shorthand-properties": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz",
-      "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-spread": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz",
-      "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-sticky-regex": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz",
-      "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-regex": "7.4.4"
-      }
-    },
-    "@babel/plugin-transform-template-literals": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz",
-      "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-annotate-as-pure": "7.0.0",
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-typeof-symbol": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz",
-      "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0"
-      }
-    },
-    "@babel/plugin-transform-unicode-regex": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz",
-      "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/helper-regex": "7.4.4",
-        "regexpu-core": "4.5.4"
-      }
-    },
-    "@babel/preset-env": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.4.4.tgz",
-      "integrity": "sha512-FU1H+ACWqZZqfw1x2G1tgtSSYSfxJLkpaUQL37CenULFARDo+h4xJoVHzRoHbK+85ViLciuI7ME4WTIhFRBBlw==",
-      "dev": true,
-      "requires": {
-        "@babel/helper-module-imports": "7.0.0",
-        "@babel/helper-plugin-utils": "7.0.0",
-        "@babel/plugin-proposal-async-generator-functions": "7.2.0",
-        "@babel/plugin-proposal-json-strings": "7.2.0",
-        "@babel/plugin-proposal-object-rest-spread": "7.4.4",
-        "@babel/plugin-proposal-optional-catch-binding": "7.2.0",
-        "@babel/plugin-proposal-unicode-property-regex": "7.4.4",
-        "@babel/plugin-syntax-async-generators": "7.2.0",
-        "@babel/plugin-syntax-json-strings": "7.2.0",
-        "@babel/plugin-syntax-object-rest-spread": "7.2.0",
-        "@babel/plugin-syntax-optional-catch-binding": "7.2.0",
-        "@babel/plugin-transform-arrow-functions": "7.2.0",
-        "@babel/plugin-transform-async-to-generator": "7.4.4",
-        "@babel/plugin-transform-block-scoped-functions": "7.2.0",
-        "@babel/plugin-transform-block-scoping": "7.4.4",
-        "@babel/plugin-transform-classes": "7.4.4",
-        "@babel/plugin-transform-computed-properties": "7.2.0",
-        "@babel/plugin-transform-destructuring": "7.4.4",
-        "@babel/plugin-transform-dotall-regex": "7.4.4",
-        "@babel/plugin-transform-duplicate-keys": "7.2.0",
-        "@babel/plugin-transform-exponentiation-operator": "7.2.0",
-        "@babel/plugin-transform-for-of": "7.4.4",
-        "@babel/plugin-transform-function-name": "7.4.4",
-        "@babel/plugin-transform-literals": "7.2.0",
-        "@babel/plugin-transform-member-expression-literals": "7.2.0",
-        "@babel/plugin-transform-modules-amd": "7.2.0",
-        "@babel/plugin-transform-modules-commonjs": "7.4.4",
-        "@babel/plugin-transform-modules-systemjs": "7.4.4",
-        "@babel/plugin-transform-modules-umd": "7.2.0",
-        "@babel/plugin-transform-named-capturing-groups-regex": "7.4.4",
-        "@babel/plugin-transform-new-target": "7.4.4",
-        "@babel/plugin-transform-object-super": "7.2.0",
-        "@babel/plugin-transform-parameters": "7.4.4",
-        "@babel/plugin-transform-property-literals": "7.2.0",
-        "@babel/plugin-transform-regenerator": "7.4.4",
-        "@babel/plugin-transform-reserved-words": "7.2.0",
-        "@babel/plugin-transform-shorthand-properties": "7.2.0",
-        "@babel/plugin-transform-spread": "7.2.2",
-        "@babel/plugin-transform-sticky-regex": "7.2.0",
-        "@babel/plugin-transform-template-literals": "7.4.4",
-        "@babel/plugin-transform-typeof-symbol": "7.2.0",
-        "@babel/plugin-transform-unicode-regex": "7.4.4",
-        "@babel/types": "7.4.4",
-        "browserslist": "4.5.5",
-        "core-js-compat": "3.0.1",
-        "invariant": "2.2.4",
-        "js-levenshtein": "1.1.6",
-        "semver": "5.7.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.7.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz",
-          "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/runtime": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.4.4.tgz",
-      "integrity": "sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg==",
-      "dev": true,
-      "requires": {
-        "regenerator-runtime": "0.13.2"
-      },
-      "dependencies": {
-        "regenerator-runtime": {
-          "version": "0.13.2",
-          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.2.tgz",
-          "integrity": "sha512-S/TQAZJO+D3m9xeN1WTI8dLKBBiRgXBlTJvbWjCThHWZj9EvHK70Ff50/tYj2J/fvBY6JtFVwRuazHN2E7M9BA==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/template": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz",
-      "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "7.0.0",
-        "@babel/parser": "7.4.4",
-        "@babel/types": "7.4.4"
-      }
-    },
-    "@babel/traverse": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.4.4.tgz",
-      "integrity": "sha512-Gw6qqkw/e6AGzlyj9KnkabJX7VcubqPtkUQVAwkc0wUMldr3A/hezNB3Rc5eIvId95iSGkGIOe5hh1kMKf951A==",
-      "dev": true,
-      "requires": {
-        "@babel/code-frame": "7.0.0",
-        "@babel/generator": "7.4.4",
-        "@babel/helper-function-name": "7.1.0",
-        "@babel/helper-split-export-declaration": "7.4.4",
-        "@babel/parser": "7.4.4",
-        "@babel/types": "7.4.4",
-        "debug": "4.1.1",
-        "globals": "11.12.0",
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.1.1",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
-          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
-          "dev": true,
-          "requires": {
-            "ms": "2.1.1"
-          }
+        "get-stdin": {
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
+            "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=",
+            "dev": true
+        },
+        "get-stream": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+            "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+            "dev": true,
+            "requires": {
+                "pump": "^3.0.0"
+            },
+            "dependencies": {
+                "pump": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+                    "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+                    "dev": true,
+                    "requires": {
+                        "end-of-stream": "^1.1.0",
+                        "once": "^1.3.1"
+                    }
+                }
+            }
+        },
+        "get-value": {
+            "version": "2.0.6",
+            "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
+            "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
+            "dev": true
+        },
+        "getpass": {
+            "version": "0.1.7",
+            "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+            "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
+            "dev": true,
+            "requires": {
+                "assert-plus": "^1.0.0"
+            }
+        },
+        "glob": {
+            "version": "7.1.3",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
+            "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
+            "dev": true,
+            "requires": {
+                "fs.realpath": "^1.0.0",
+                "inflight": "^1.0.4",
+                "inherits": "2",
+                "minimatch": "^3.0.4",
+                "once": "^1.3.0",
+                "path-is-absolute": "^1.0.0"
+            }
+        },
+        "glob-parent": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
+            "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
+            "dev": true,
+            "requires": {
+                "is-glob": "^3.1.0",
+                "path-dirname": "^1.0.0"
+            }
+        },
+        "glob-to-regexp": {
+            "version": "0.3.0",
+            "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz",
+            "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=",
+            "dev": true
+        },
+        "global-modules": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
+            "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
+            "dev": true,
+            "requires": {
+                "global-prefix": "^1.0.1",
+                "is-windows": "^1.0.1",
+                "resolve-dir": "^1.0.0"
+            }
+        },
+        "global-prefix": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
+            "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
+            "dev": true,
+            "requires": {
+                "expand-tilde": "^2.0.2",
+                "homedir-polyfill": "^1.0.1",
+                "ini": "^1.3.4",
+                "is-windows": "^1.0.1",
+                "which": "^1.2.14"
+            },
+            "dependencies": {
+                "which": {
+                    "version": "1.3.1",
+                    "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+                    "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+                    "dev": true,
+                    "requires": {
+                        "isexe": "^2.0.0"
+                    }
+                }
+            }
         },
         "globals": {
-          "version": "11.12.0",
-          "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-          "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
-          "dev": true
+            "version": "9.18.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+            "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=",
+            "dev": true
         },
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
+        "globby": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz",
+            "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=",
+            "dev": true,
+            "requires": {
+                "array-union": "^1.0.1",
+                "arrify": "^1.0.0",
+                "glob": "^7.0.3",
+                "object-assign": "^4.0.1",
+                "pify": "^2.0.0",
+                "pinkie-promise": "^2.0.0"
+            },
+            "dependencies": {
+                "glob": {
+                    "version": "7.1.2",
+                    "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+                    "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
+                    "dev": true,
+                    "requires": {
+                        "fs.realpath": "^1.0.0",
+                        "inflight": "^1.0.4",
+                        "inherits": "2",
+                        "minimatch": "^3.0.4",
+                        "once": "^1.3.0",
+                        "path-is-absolute": "^1.0.0"
+                    }
+                },
+                "minimatch": {
+                    "version": "3.0.4",
+                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+                    "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
+                    "dev": true,
+                    "requires": {
+                        "brace-expansion": "^1.1.7"
+                    }
+                }
+            }
         },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
-          "dev": true
-        }
-      }
-    },
-    "@babel/types": {
-      "version": "7.4.4",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.4.tgz",
-      "integrity": "sha512-dOllgYdnEFOebhkKCjzSVFqw/PmmB8pH6RGOWkY4GsboQNd47b1fBThBSwlHAq9alF9vc1M3+6oqR47R50L0tQ==",
-      "dev": true,
-      "requires": {
-        "esutils": "2.0.2",
-        "lodash": "4.17.15",
-        "to-fast-properties": "2.0.0"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
+        "globjoin": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz",
+            "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=",
+            "dev": true
+        },
+        "globule": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
+            "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
+            "dev": true,
+            "requires": {
+                "glob": "~7.1.1",
+                "lodash": "~4.17.10",
+                "minimatch": "~3.0.2"
+            }
         },
-        "to-fast-properties": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
-          "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
-          "dev": true
-        }
-      }
-    },
-    "@covalent/core": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/@covalent/core/-/core-2.1.0.tgz",
-      "integrity": "sha512-I3/VL76E198y8O2vWXci7uLEfBEB9dO8uZWwaJN3RFlSuS/HCzc/NUrElJ9aRwgmTm8KLQgJheVbg/CRQbn2Ug==",
-      "requires": {
-        "tslib": "1.10.0"
-      },
-      "dependencies": {
-        "tslib": {
-          "version": "1.10.0",
-          "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
-          "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
-        }
-      }
-    },
-    "@mrmlnc/readdir-enhanced": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
-      "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
-      "dev": true,
-      "requires": {
-        "call-me-maybe": "1.0.1",
-        "glob-to-regexp": "0.3.0"
-      }
-    },
-    "@nifi-fds/core": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/@nifi-fds/core/-/core-0.2.0.tgz",
-      "integrity": "sha512-6yadtM2ahtkeFnuYN+D6M0qB81y2F3uBAC6ZovXe1c1lSocXSuJCoFJq9NRW6KFFqYAQnOyZi1+hA1Kw2+UfXg=="
-    },
-    "@nodelib/fs.stat": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
-      "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
-      "dev": true
-    },
-    "@samverschueren/stream-to-observable": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz",
-      "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==",
-      "dev": true,
-      "requires": {
-        "any-observable": "0.3.0"
-      }
-    },
-    "@types/events": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
-      "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==",
-      "dev": true
-    },
-    "@types/glob": {
-      "version": "7.1.1",
-      "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz",
-      "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==",
-      "dev": true,
-      "requires": {
-        "@types/events": "3.0.0",
-        "@types/minimatch": "3.0.3",
-        "@types/node": "6.0.106"
-      }
-    },
-    "@types/minimatch": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
-      "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
-      "dev": true
-    },
-    "@types/node": {
-      "version": "6.0.106",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.106.tgz",
-      "integrity": "sha1-ORvDWYq1gjVj9xVYRyEhUok+3Nc=",
-      "dev": true
-    },
-    "@types/normalize-package-data": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
-      "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
-      "dev": true
-    },
-    "@types/q": {
-      "version": "0.0.32",
-      "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz",
-      "integrity": "sha1-vShOV8hPEyXacCur/IKlMoGQwMU=",
-      "dev": true
-    },
-    "@types/selenium-webdriver": {
-      "version": "3.0.10",
-      "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-3.0.10.tgz",
-      "integrity": "sha512-ikB0JHv6vCR1KYUQAzTO4gi/lXLElT4Tx+6De2pc/OZwizE9LRNiTa+U8TBFKBD/nntPnr/MPSHSnOTybjhqNA==",
-      "dev": true
-    },
-    "@types/source-list-map": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
-      "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
-      "dev": true
-    },
-    "@types/unist": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
-      "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==",
-      "dev": true
-    },
-    "@types/vfile": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/@types/vfile/-/vfile-3.0.2.tgz",
-      "integrity": "sha512-b3nLFGaGkJ9rzOcuXRfHkZMdjsawuDD0ENL9fzTophtBg8FJHSGbH7daXkEpcwy3v7Xol3pAvsmlYyFhR4pqJw==",
-      "dev": true,
-      "requires": {
-        "@types/node": "6.0.106",
-        "@types/unist": "2.0.3",
-        "@types/vfile-message": "1.0.1"
-      }
-    },
-    "@types/vfile-message": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@types/vfile-message/-/vfile-message-1.0.1.tgz",
-      "integrity": "sha512-mlGER3Aqmq7bqR1tTTIVHq8KSAFFRyGbrxuM8C/H82g6k7r2fS+IMEkIu3D7JHzG10NvPdR8DNx0jr0pwpp4dA==",
-      "dev": true,
-      "requires": {
-        "@types/node": "6.0.106",
-        "@types/unist": "2.0.3"
-      }
-    },
-    "@types/webpack-sources": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz",
-      "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==",
-      "dev": true,
-      "requires": {
-        "@types/node": "6.0.106",
-        "@types/source-list-map": "0.1.2",
-        "source-map": "0.6.1"
-      },
-      "dependencies": {
-        "source-map": {
-          "version": "0.6.1",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-          "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-          "dev": true
-        }
-      }
-    },
-    "@typescript-eslint/eslint-plugin": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.6.0.tgz",
-      "integrity": "sha512-U224c29E2lo861TQZs6GSmyC0OYeRNg6bE9UVIiFBxN2MlA0nq2dCrgIVyyRbC05UOcrgf2Wk/CF2gGOPQKUSQ==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/parser": "1.6.0",
-        "@typescript-eslint/typescript-estree": "1.6.0",
-        "requireindex": "1.2.0",
-        "tsutils": "3.10.0"
-      }
-    },
-    "@typescript-eslint/parser": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-1.6.0.tgz",
-      "integrity": "sha512-VB9xmSbfafI+/kI4gUK3PfrkGmrJQfh0N4EScT1gZXSZyUxpsBirPL99EWZg9MmPG0pzq/gMtgkk7/rAHj4aQw==",
-      "dev": true,
-      "requires": {
-        "@typescript-eslint/typescript-estree": "1.6.0",
-        "eslint-scope": "4.0.3",
-        "eslint-visitor-keys": "1.0.0"
-      }
-    },
-    "@typescript-eslint/typescript-estree": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-1.6.0.tgz",
-      "integrity": "sha512-A4CanUwfaG4oXobD5y7EXbsOHjCwn8tj1RDd820etpPAjH+Icjc2K9e/DQM1Hac5zH2BSy+u6bjvvF2wwREvYA==",
-      "dev": true,
-      "requires": {
-        "lodash.unescape": "4.0.1",
-        "semver": "5.5.0"
-      },
-      "dependencies": {
-        "semver": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
-          "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
-          "dev": true
-        }
-      }
-    },
-    "@webassemblyjs/ast": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
-      "integrity": "sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/helper-module-context": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/wast-parser": "1.8.5"
-      }
-    },
-    "@webassemblyjs/floating-point-hex-parser": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz",
-      "integrity": "sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-api-error": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz",
-      "integrity": "sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-buffer": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz",
-      "integrity": "sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-code-frame": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz",
-      "integrity": "sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/wast-printer": "1.8.5"
-      }
-    },
-    "@webassemblyjs/helper-fsm": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz",
-      "integrity": "sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-module-context": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz",
-      "integrity": "sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "mamacro": "0.0.3"
-      }
-    },
-    "@webassemblyjs/helper-wasm-bytecode": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz",
-      "integrity": "sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ==",
-      "dev": true
-    },
-    "@webassemblyjs/helper-wasm-section": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz",
-      "integrity": "sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-buffer": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/wasm-gen": "1.8.5"
-      }
-    },
-    "@webassemblyjs/ieee754": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz",
-      "integrity": "sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g==",
-      "dev": true,
-      "requires": {
-        "@xtuc/ieee754": "1.2.0"
-      }
-    },
-    "@webassemblyjs/leb128": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.8.5.tgz",
-      "integrity": "sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A==",
-      "dev": true,
-      "requires": {
-        "@xtuc/long": "4.2.2"
-      }
-    },
-    "@webassemblyjs/utf8": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.8.5.tgz",
-      "integrity": "sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw==",
-      "dev": true
-    },
-    "@webassemblyjs/wasm-edit": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz",
-      "integrity": "sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-buffer": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/helper-wasm-section": "1.8.5",
-        "@webassemblyjs/wasm-gen": "1.8.5",
-        "@webassemblyjs/wasm-opt": "1.8.5",
-        "@webassemblyjs/wasm-parser": "1.8.5",
-        "@webassemblyjs/wast-printer": "1.8.5"
-      }
-    },
-    "@webassemblyjs/wasm-gen": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz",
-      "integrity": "sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/ieee754": "1.8.5",
-        "@webassemblyjs/leb128": "1.8.5",
-        "@webassemblyjs/utf8": "1.8.5"
-      }
-    },
-    "@webassemblyjs/wasm-opt": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz",
-      "integrity": "sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-buffer": "1.8.5",
-        "@webassemblyjs/wasm-gen": "1.8.5",
-        "@webassemblyjs/wasm-parser": "1.8.5"
-      }
-    },
-    "@webassemblyjs/wasm-parser": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz",
-      "integrity": "sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/helper-api-error": "1.8.5",
-        "@webassemblyjs/helper-wasm-bytecode": "1.8.5",
-        "@webassemblyjs/ieee754": "1.8.5",
-        "@webassemblyjs/leb128": "1.8.5",
-        "@webassemblyjs/utf8": "1.8.5"
-      }
-    },
-    "@webassemblyjs/wast-parser": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz",
-      "integrity": "sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/floating-point-hex-parser": "1.8.5",
-        "@webassemblyjs/helper-api-error": "1.8.5",
-        "@webassemblyjs/helper-code-frame": "1.8.5",
-        "@webassemblyjs/helper-fsm": "1.8.5",
-        "@xtuc/long": "4.2.2"
-      }
-    },
-    "@webassemblyjs/wast-printer": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz",
-      "integrity": "sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg==",
-      "dev": true,
-      "requires": {
-        "@webassemblyjs/ast": "1.8.5",
-        "@webassemblyjs/wast-parser": "1.8.5",
-        "@xtuc/long": "4.2.2"
-      }
-    },
-    "@xtuc/ieee754": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
-      "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
-      "dev": true
-    },
-    "@xtuc/long": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
-      "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
-      "dev": true
-    },
-    "abbrev": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
-      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
-      "dev": true
-    },
-    "accepts": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
-      "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
-      "dev": true,
-      "requires": {
-        "mime-types": "2.1.18",
-        "negotiator": "0.6.1"
-      }
-    },
-    "acorn": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz",
-      "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==",
-      "dev": true
-    },
-    "acorn-dynamic-import": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz",
-      "integrity": "sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw==",
-      "dev": true
-    },
-    "acorn-jsx": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz",
-      "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==",
-      "dev": true
-    },
-    "adm-zip": {
-      "version": "0.4.11",
-      "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.11.tgz",
-      "integrity": "sha512-L8vcjDTCOIJk7wFvmlEUN7AsSb8T+2JrdP7KINBjzr24TJ5Mwj590sLu3BC7zNZowvJWa/JtPmD8eJCzdtDWjA==",
-      "dev": true
-    },
-    "after": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz",
-      "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=",
-      "dev": true
-    },
-    "ajv": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-      "dev": true,
-      "requires": {
-        "co": "4.6.0",
-        "fast-deep-equal": "1.1.0",
-        "fast-json-stable-stringify": "2.0.0",
-        "json-schema-traverse": "0.3.1"
-      }
-    },
-    "ajv-errors": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
-      "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
-      "dev": true
-    },
-    "ajv-keywords": {
-      "version": "3.4.0",
-      "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.0.tgz",
-      "integrity": "sha512-aUjdRFISbuFOl0EIZc+9e4FfZp0bDZgAdOOf30bJmw8VM9v84SHyVyxDfbWxpGYbdZD/9XoKxfHVNmxPkhwyGw==",
-      "dev": true
-    },
-    "alphanum-sort": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
-      "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
-      "dev": true
-    },
-    "amdefine": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
-      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
-      "dev": true
-    },
-    "angular2-jwt": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/angular2-jwt/-/angular2-jwt-0.2.3.tgz",
-      "integrity": "sha1-VO/do87tuoX2o3sWXyKsIrit8CE="
-    },
-    "angular2-moment": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/angular2-moment/-/angular2-moment-1.9.0.tgz",
-      "integrity": "sha512-ybPjYizpKVWAI2Z4AqxAS6s3FMkF3+zRpfvxX1wIdSJUFjl83XxQ5f2yn7retX68NSYZZ/JTK9KGnvOzZfrIZw==",
-      "requires": {
-        "moment": "2.22.1"
-      }
-    },
-    "ansi-colors": {
-      "version": "3.2.4",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
-      "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
-      "dev": true
-    },
-    "ansi-escapes": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
-      "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
-      "dev": true
-    },
-    "ansi-html": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
-      "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
-      "dev": true
-    },
-    "ansi-regex": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
-      "dev": true
-    },
-    "ansi-styles": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-      "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-      "dev": true
-    },
-    "any-observable": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz",
-      "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==",
-      "dev": true
-    },
-    "anymatch": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
-      "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
-      "dev": true,
-      "requires": {
-        "micromatch": "3.1.10",
-        "normalize-path": "2.1.1"
-      }
-    },
-    "append-transform": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz",
-      "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==",
-      "dev": true,
-      "requires": {
-        "default-require-extensions": "2.0.0"
-      }
-    },
-    "aproba": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-      "integrity": "sha1-aALmJk79GMeQobDVF/DyYnvyyUo=",
-      "dev": true
-    },
-    "are-we-there-yet": {
-      "version": "1.1.5",
-      "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
-      "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
-      "dev": true,
-      "requires": {
-        "delegates": "1.0.0",
-        "readable-stream": "2.3.6"
-      }
-    },
-    "argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "dev": true,
-      "requires": {
-        "sprintf-js": "1.0.3"
-      }
-    },
-    "aria-query": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-3.0.0.tgz",
-      "integrity": "sha1-ZbP8wcoRVajJrmTW7uKX8V1RM8w=",
-      "dev": true,
-      "requires": {
-        "ast-types-flow": "0.0.7",
-        "commander": "2.20.0"
-      }
-    },
-    "arr-diff": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
-      "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
-      "dev": true
-    },
-    "arr-flatten": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-      "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
-      "dev": true
-    },
-    "arr-union": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
-      "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
-      "dev": true
-    },
-    "array-find-index": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
-      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
-      "dev": true
-    },
-    "array-flatten": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
-      "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
-      "dev": true
-    },
-    "array-includes": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz",
-      "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=",
-      "dev": true,
-      "requires": {
-        "define-properties": "1.1.3",
-        "es-abstract": "1.13.0"
-      }
-    },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "1.0.3"
-      }
-    },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
-    "arraybuffer.slice": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz",
-      "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==",
-      "dev": true
-    },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-      "dev": true
-    },
-    "asn1": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz",
-      "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=",
-      "dev": true
-    },
-    "asn1.js": {
-      "version": "4.10.1",
-      "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
-      "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
-      "dev": true,
-      "requires": {
-        "bn.js": "4.11.8",
-        "inherits": "2.0.3",
-        "minimalistic-assert": "1.0.1"
-      }
-    },
-    "assert": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz",
-      "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=",
-      "dev": true,
-      "requires": {
-        "util": "0.10.3"
-      },
-      "dependencies": {
-        "inherits": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
-          "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
-          "dev": true
+        "gonzales-pe": {
+            "version": "4.2.4",
+            "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.2.4.tgz",
+            "integrity": "sha512-v0Ts/8IsSbh9n1OJRnSfa7Nlxi4AkXIsWB6vPept8FDbL4bXn3FNuxjYtO/nmBGu7GDkL9MFeGebeSu6l55EPQ==",
+            "dev": true,
+            "requires": {
+                "minimist": "1.1.x"
+            },
+            "dependencies": {
+                "minimist": {
+                    "version": "1.1.3",
+                    "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
+                    "integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=",
+                    "dev": true
+                }
+            }
         },
-        "util": {
-          "version": "0.10.3",
-          "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
-          "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
-          "dev": true,
-          "requires": {
-            "inherits": "2.0.1"
-          }
-        }
-      }
-    },
-    "assert-plus": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-      "dev": true
-    },
-    "assign-symbols": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
-      "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
-      "dev": true
-    },
-    "ast-types": {
-      "version": "0.9.6",
-      "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
-      "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=",
-      "dev": true
-    },
-    "ast-types-flow": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz",
-      "integrity": "sha1-9wtzXGvKGlycItmCw+Oef+ujva0=",
-      "dev": true
-    },
-    "astral-regex": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
-      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
-      "dev": true
-    },
-    "async": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-      "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-      "dev": true
-    },
-    "async-each": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
-      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
-      "dev": true
-    },
-    "async-foreach": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
-      "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=",
-      "dev": true
-    },
-    "async-limiter": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
-      "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg==",
-      "dev": true
-    },
-    "asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
-    },
-    "atob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.1.tgz",
-      "integrity": "sha1-ri1acpR38onWDdf5amMUoi3Wwio=",
-      "dev": true
-    },
-    "autoprefixer": {
-      "version": "9.5.1",
-      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.5.1.tgz",
-      "integrity": "sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ==",
-      "dev": true,
-      "requires": {
-        "browserslist": "4.5.5",
-        "caniuse-lite": "1.0.30000963",
-        "normalize-range": "0.1.2",
-        "num2fraction": "1.2.2",
-        "postcss": "7.0.14",
-        "postcss-value-parser": "3.3.1"
-      }
-    },
-    "aws-sign2": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-      "dev": true
-    },
-    "aws4": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz",
-      "integrity": "sha1-1NDpudv8p3vwjusKikcVUP454ok=",
-      "dev": true
-    },
-    "axobject-query": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz",
-      "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==",
-      "dev": true,
-      "requires": {
-        "ast-types-flow": "0.0.7"
-      }
-    },
-    "babel-code-frame": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
-      "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
-      "dev": true,
-      "requires": {
-        "chalk": "1.1.3",
-        "esutils": "2.0.2",
-        "js-tokens": "3.0.2"
-      }
-    },
-    "babel-generator": {
-      "version": "6.26.1",
-      "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz",
-      "integrity": "sha1-GERAjTuPDTWkBOp6wYDwh6YBvZA=",
-      "dev": true,
-      "requires": {
-        "babel-messages": "6.23.0",
-        "babel-runtime": "6.26.0",
-        "babel-types": "6.26.0",
-        "detect-indent": "4.0.0",
-        "jsesc": "1.3.0",
-        "lodash": "4.17.15",
-        "source-map": "0.5.7",
-        "trim-right": "1.0.1"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
+        "graceful-fs": {
+            "version": "4.1.15",
+            "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
+            "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==",
+            "dev": true
+        },
+        "hammerjs": {
+            "version": "2.0.8",
+            "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
+            "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
+        },
+        "handle-thing": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz",
+            "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==",
+            "dev": true
         },
-        "source-map": {
-          "version": "0.5.7",
-          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
-          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
-          "dev": true
-        }
-      }
-    },
-    "babel-loader": {
-      "version": "8.0.5",
-      "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.5.tgz",
-      "integrity": "sha512-NTnHnVRd2JnRqPC0vW+iOQWU5pchDbYXsG2E6DMXEpMfUcQKclF9gmf3G3ZMhzG7IG9ji4coL0cm+FxeWxDpnw==",
-      "dev": true,
-      "requires": {
-        "find-cache-dir": "2.1.0",
-        "loader-utils": "1.2.3",
-        "mkdirp": "0.5.1",
-        "util.promisify": "1.0.0"
-      }
-    },
-    "babel-messages": {
-      "version": "6.23.0",
-      "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
-      "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0"
-      }
-    },
-    "babel-plugin-istanbul": {
-      "version": "5.1.4",
-      "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.1.4.tgz",
-      "integrity": "sha512-dySz4VJMH+dpndj0wjJ8JPs/7i1TdSPb1nRrn56/92pKOF9VKC1FMFJmMXjzlGGusnCAqujP6PBCiKq0sVA+YQ==",
-      "dev": true,
-      "requires": {
-        "find-up": "3.0.0",
-        "istanbul-lib-instrument": "3.3.0",
-        "test-exclude": "5.2.3"
-      },
-      "dependencies": {
-        "find-up": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
-          "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
-          "dev": true,
-          "requires": {
-            "locate-path": "3.0.0"
-          }
+        "handlebars": {
+            "version": "4.4.3",
+            "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.4.3.tgz",
+            "integrity": "sha512-B0W4A2U1ww3q7VVthTKfh+epHx+q4mCt6iK+zEAzbMBpWQAwxCeKxEGpj/1oQTpzPXDNSOG7hmG14TsISH50yw==",
+            "dev": true,
+            "requires": {
+                "neo-async": "^2.6.0",
+                "optimist": "^0.6.1",
+                "source-map": "^0.6.1",
+                "uglify-js": "^3.1.4"
+            },
+            "dependencies": {
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+                    "dev": true
+                }
+            }
         },
-        "istanbul-lib-coverage": {
-          "version": "2.0.5",
-          "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz",
-          "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==",
-          "dev": true
+        "har-schema": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
+            "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
+            "dev": true
         },
-        "istanbul-lib-instrument": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz",
-          "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==",
-          "dev": true,
-          "requires": {
-            "@babel/generator": "7.4.4",
-            "@babel/parser": "7.4.4",
-            "@babel/template": "7.4.4",
-            "@babel/traverse": "7.4.4",
-            "@babel/types": "7.4.4",
-            "istanbul-lib-coverage": "2.0.5",
-            "semver": "6.1.3"
-          }
+        "har-validator": {
+            "version": "5.0.3",
+            "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz",
+            "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=",
+            "dev": true,
+            "requires": {
+                "ajv": "^5.1.0",
+                "har-schema": "^2.0.0"
+            }
         },
-        "locate-path": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-          "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
-          "dev": true,
-          "requires": {
-            "p-locate": "3.0.0",
-            "path-exists": "3.0.0"
-          }
+        "has": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+            "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+            "dev": true,
+            "requires": {
+                "function-bind": "^1.1.1"
+            }
         },
-        "p-limit": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
-          "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
-          "dev": true,
-          "requires": {
-            "p-try": "2.2.0"
-          }
+        "has-ansi": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+            "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+            "dev": true,
+            "requires": {
+                "ansi-regex": "^2.0.0"
+            }
         },
-        "p-locate": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
-          "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
-          "dev": true,
-          "requires": {
-            "p-limit": "2.2.0"
-          }
+        "has-binary2": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz",
+            "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==",
+            "dev": true,
+            "requires": {
+                "isarray": "2.0.1"
+            },
+            "dependencies": {
+                "isarray": {
+                    "version": "2.0.1",
+                    "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz",
+                    "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=",
+                    "dev": true
+                }
+            }
         },
-        "p-try": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-          "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-          "dev": true
+        "has-cors": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
+            "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
+            "dev": true
         },
-        "path-exists": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
-          "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
-          "dev": true
+        "has-flag": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
+            "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
+            "dev": true
         },
-        "semver": {
-          "version": "6.1.3",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-6.1.3.tgz",
-          "integrity": "sha512-aymF+56WJJMyXQHcd4hlK4N75rwj5RQpfW8ePlQnJsTYOBLlLbcIErR/G1s9SkIvKBqOudR3KAx4wEqP+F1hNQ==",
-          "dev": true
-        }
-      }
-    },
-    "babel-polyfill": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
-      "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0",
-        "core-js": "2.5.5",
-        "regenerator-runtime": "0.10.5"
-      },
-      "dependencies": {
-        "regenerator-runtime": {
-          "version": "0.10.5",
-          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
-          "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
-          "dev": true
-        }
-      }
-    },
-    "babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "dev": true,
-      "requires": {
-        "core-js": "2.5.5",
-        "regenerator-runtime": "0.11.1"
-      }
-    },
-    "babel-template": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
-      "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0",
-        "babel-traverse": "6.26.0",
-        "babel-types": "6.26.0",
-        "babylon": "6.18.0",
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "babel-traverse": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
-      "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
-      "dev": true,
-      "requires": {
-        "babel-code-frame": "6.26.0",
-        "babel-messages": "6.23.0",
-        "babel-runtime": "6.26.0",
-        "babel-types": "6.26.0",
-        "babylon": "6.18.0",
-        "debug": "2.6.9",
-        "globals": "9.18.0",
-        "invariant": "2.2.4",
-        "lodash": "4.17.15"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
+        "has-symbols": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
+            "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
+            "dev": true
         },
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "babel-types": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
-      "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "6.26.0",
-        "esutils": "2.0.2",
-        "lodash": "4.17.15",
-        "to-fast-properties": "1.0.3"
-      },
-      "dependencies": {
-        "lodash": {
-          "version": "4.17.15",
-          "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
-          "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
-          "dev": true
-        }
-      }
-    },
-    "babylon": {
-      "version": "6.18.0",
-      "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
-      "integrity": "sha1-ry87iPpvXB5MY00aD46sT1WzleM=",
-      "dev": true
-    },
-    "backo2": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
-      "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
-      "dev": true
-    },
-    "bail": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.3.tgz",
-      "integrity": "sha512-1X8CnjFVQ+a+KW36uBNMTU5s8+v5FzeqrP7hTG5aTb4aPreSbZJlhwPon9VKMuEVgV++JM+SQrALY3kr7eswdg==",
-      "dev": true
-    },
-    "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
-      "dev": true
-    },
-    "base": {
-      "version": "0.11.2",
-      "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
-      "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
-      "dev": true,
-      "requires": {
-        "cache-base": "1.0.1",
-        "class-utils": "0.3.6",
-        "component-emitter": "1.2.1",
-        "define-property": "1.0.0",
-        "isobject": "3.0.1",
-        "mixin-deep": "1.3.2",
-        "pascalcase": "0.1.1"
-      },
-      "dependencies": {
-        "define-property": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
-          "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
-          "dev": true,
-          "requires": {
-            "is-descriptor": "1.0.2"
-          }
+        "has-unicode": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+            "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+            "dev": true
         },
-        "is-accessor-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
-          "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
+        "has-value": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
+            "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
+            "dev": true,
+            "requires": {
+                "get-value": "^2.0.6",
+                "has-values": "^1.0.0",
+                "isobject": "^3.0.0"
+            },
+            "dependencies": {
+                "isobject": {
+                    "version": "3.0.1",
+                    "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+                    "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
+                    "dev": true
+                }
+            }
         },
-        "is-data-descriptor": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
-          "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
-          "dev": true,
-          "requires": {
-            "kind-of": "6.0.2"
-          }
+        "has-values": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
+            "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
+            "dev": true,
+            "requires": {
+                "is-number": "^3.0.0",
+                "kind-of": "^4.0.0"
+            },
+            "dependencies": {
+                "is-number": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+                    "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+                    "dev": true,
+                    "requires": {
+                        "kind-of": "^3.0.2"
+                    },
+                    "dependencies": {
+                        "kind-of": {
+                            "version": "3.2.2",
+                            "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                            "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                            "dev": true,
+                            "requires": {
+                                "is-buffer": "^1.1.5"
+                            }
+                        }
+                    }
+                },
+                "kind-of": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+                    "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+                    "dev": true,
+                    "requires": {
+                        "is-buffer": "^1.1.5"
+                    }
+                }
+            }
         },
-        "is-descriptor": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
-          "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
-          "dev": true,
-          "requires": {
-            "is-accessor-descriptor": "1.0.0",
-            "is-data-descriptor": "1.0.0",
-            "kind-of": "6.0.2"
-          }
+        "hash-base": {
+            "version": "3.0.4",
+            "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+            "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.1",
+                "safe-buffer": "^5.0.1"
+            }
         },
-        "isobject": {
-          "version": "3.0.1",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
+        "hash.js": {
+            "version": "1.1.7",
+            "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+            "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.3",
+                "minimalistic-assert": "^1.0.1"
+            }
         },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
-    "base64-arraybuffer": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz",
-      "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=",
-      "dev": true
-    },
-    "base64-js": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
-      "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==",
-      "dev": true
-    },
-    "base64id": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz",
-      "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=",
-      "dev": true
-    },
-    "batch": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
-      "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=",
-      "dev": true
-    },
-    "bcrypt-pbkdf": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz",
-      "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "tweetnacl": "0.14.5"
-      }
-    },
-    "better-assert": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz",
-      "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=",
-      "dev": true,
-      "requires": {
-        "callsite": "1.0.0"
-      }
-    },
-    "big.js": {
-      "version": "5.2.2",
-      "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
-      "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
-      "dev": true
-    },
-    "binary-extensions": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
-      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
-      "dev": true
-    },
-    "blob": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz",
-      "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==",
-      "dev": true
-    },
-    "block-stream": {
-      "version": "0.0.9",
-      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
-      "dev": true,
-      "requires": {
-        "inherits": "2.0.3"
-      }
-    },
-    "blocking-proxy": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/blocking-proxy/-/blocking-proxy-1.0.1.tgz",
-      "integrity": "sha512-KE8NFMZr3mN2E0HcvCgRtX7DjhiIQrwle+nSVJVC/yqFb9+xznHl2ZcoBp2L9qzkI4t4cBFJ1efXF8Dwi132RA==",
-      "dev": true,
-      "requires": {
-        "minimist": "1.2.0"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
-          "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
-          "dev": true
-        }
-      }
-    },
-    "bluebird": {
-      "version": "3.5.5",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
-      "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==",
-      "dev": true
-    },
-    "bn.js": {
-      "version": "4.11.8",
-      "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
-      "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
-      "dev": true
-    },
-    "body-parser": {
-      "version": "1.19.0",
-      "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
-      "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
-      "dev": true,
-      "requires": {
-        "bytes": "3.1.0",
-        "content-type": "1.0.4",
-        "debug": "2.6.9",
-        "depd": "1.1.2",
-        "http-errors": "1.7.2",
-        "iconv-lite": "0.4.24",
-        "on-finished": "2.3.0",
-        "qs": "6.7.0",
-        "raw-body": "2.4.0",
-        "type-is": "1.6.18"
-      },
-      "dependencies": {
-        "bytes": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
-          "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
-          "dev": true
+        "he": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+            "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+            "dev": true
+        },
+        "hex-color-regex": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
+            "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
+            "dev": true
+        },
+        "hmac-drbg": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+            "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+            "dev": true,
+            "requires": {
+                "hash.js": "^1.0.3",
+                "minimalistic-assert": "^1.0.0",
+                "minimalistic-crypto-utils": "^1.0.1"
+            }
         },
-        "debug": {
-          "version": "2.6.9",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
-          "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
+        "homedir-polyfill": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
+            "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
+            "dev": true,
+            "requires": {
+                "parse-passwd": "^1.0.0"
+            }
+        },
+        "hosted-git-info": {
+            "version": "2.6.0",
+            "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz",
+            "integrity": "sha1-IyNbKasjDFdqqw1PE/wEawsDgiI=",
+            "dev": true
+        },
+        "hpack.js": {
+            "version": "2.1.6",
+            "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+            "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=",
+            "dev": true,
+            "requires": {
+                "inherits": "^2.0.1",
+                "obuf": "^1.0.0",
+                "readable-stream": "^2.0.1",
+                "wbuf": "^1.1.0"
+            }
+        },
+        "hsl-regex": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz",
+            "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=",
+            "dev": true
+        },
+        "hsla-regex": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
+            "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
+            "dev": true
+        },
+        "html-comment-regex": {
+            "version": "1.1.2",
+            "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
+            "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==",
+            "dev": true
+        },
+        "html-entities": {
+            "version": "1.2.1",
+            "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
+            "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
+            "dev": true
+        },
+        "html-loader": {
+            "version": "0.5.5",
+            "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.5.5.tgz",
+            "integrity": "sha512-7hIW7YinOYUpo//kSYcPB6dCKoceKLmOwjEMmhIobHuWGDVl0Nwe4l68mdG/Ru0wcUxQjVMEoZpkalZ/SE7zog==",
+            "dev": true,
+            "requires": {
+                "es6-templates": "^0.2.3",
+                "fastparse": "^1.1.1",
+                "html-minifier": "^3.5.8",
+                "loader-utils": "^1.1.0",
+                "object-assign": "^4.1.1"
+            }
+        },
+        "html-minifier": {
+            "version": "3.5.21",
+            "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
+            "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+            "dev": true,
+            "requires": {
+                "camel-case": "3.0.x",
+                "clean-css": "4.2.x",
+                "commander": "2.17.x",
+                "he": "1.2.x",
+                "param-case": "2.1.x",
+                "relateurl": "0.2.x",
+                "uglify-js": "3.4.x"
+            },
+            "dependencies": {
+                "commander": {
+                    "version": "2.17.1",
+                    "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
+                    "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==",
+                    "dev": true
+                },
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+                    "dev": true
+                },
+                "uglify-js": {
+                    "version": "3.4.10",
+                    "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
+                    "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
+                    "dev": true,
+                    "requires": {
+                        "commander": "~2.19.0",
+                        "source-map": "~0.6.1"
+                    },
+                    "dependencies": {
+                        "commander": {
+                            "version": "2.19.0",
+                            "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
+                            "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
+                            "dev": true
+                        }
+                    }
+                }
+            }
+        },
+        "html-tags": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
+            "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=",
+            "dev": true
+        },
+        "html-webpack-plugin": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
+            "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s=",
+            "dev": true,
+            "requires": {
+                "html-minifier": "^3.2.3",
+                "loader-utils": "^0.2.16",
+                "lodash": "^4.17.3",
+                "pretty-error": "^2.0.2",
+                "tapable": "^1.0.0",
+                "toposort": "^1.0.0",
+                "util.promisify": "1.0.0"
+            },
+            "dependencies": {
+                "big.js": {
+                    "version": "3.2.0",
+                    "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
+                    "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
+                    "dev": true
+                },
+                "loader-utils": {
+                    "version": "0.2.17",
+                    "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
+                    "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
+                    "dev": true,
+                    "requires": {
+                        "big.js": "^3.1.3",
+                        "emojis-list": "^2.0.0",
+                        "json5": "^0.5.0",
+                        "object-assign": "^4.0.1"
+                    }
+                }
+            }
+        },
+        "htmlparser2": {
+            "version": "3.10.1",
+            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
+            "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
+            "dev": true,
+            "requires": {
+                "domelementtype": "^1.3.1",
+                "domhandler": "^2.3.0",
+                "domutils": "^1.5.1",
+                "entities": "^1.1.1",
+                "inherits": "^2.0.1",
+                "readable-stream": "^3.1.1"
+            },
+            "dependencies": {
+                "readable-stream": {
+                    "version": "3.3.0",
+                    "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz",
+                    "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==",
+                    "dev": true,
+                    "requires": {
+                        "inherits": "^2.0.3",
+                        "string_decoder": "^1.1.1",
+                        "util-deprecate": "^1.0.1"
+                    }
+                }
+            }
+        },
+        "http-deceiver": {
+            "version": "1.2.7",
+            "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+            "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=",
+            "dev": true
         },
         "http-errors": {
-          "version": "1.7.2",
-          "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
-          "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
-          "dev": true,
-          "requires": {
-            "depd": "1.1.2",
-            "inherits": "2.0.3",
-            "setprototypeof": "1.1.1",
-            "statuses": "1.5.0",
-            "toidentifier": "1.0.0"
-          }
+            "version": "1.6.3",
+            "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+            "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+            "dev": true,
+            "requires": {
+                "depd": "~1.1.2",
+                "inherits": "2.0.3",
+                "setprototypeof": "1.1.0",
+                "statuses": ">= 1.4.0 < 2"
+            }
+        },
+        "http-parser-js": {
+            "version": "0.5.0",
+            "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.0.tgz",
+            "integrity": "sha512-cZdEF7r4gfRIq7ezX9J0T+kQmJNOub71dWbgAXVHDct80TKP4MCETtZQ31xyv38UwgzkWPYF/Xc0ge55dW9Z9w==",
+            "dev": true
+        },
+        "http-proxy": {
+            "version": "1.17.0",
+            "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
+            "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+            "dev": true,
+            "requires": {
+                "eventemitter3": "^3.0.0",
+                "follow-redirects": "^1.0.0",
+                "requires-port": "^1.0.0"
+            }
+        },
+        "http-proxy-middleware": {
+            "version": "0.19.1",
+            "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
+            "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
+            "dev": true,
+            "requires": {
+                "http-proxy": "^1.17.0",
+                "is-glob": "^4.0.0",
+                "lodash": "^4.17.11",
+                "micromatch": "^3.1.10"
+            },
+            "dependencies": {
+                "eventemitter3": {
+                    "version": "3.1.2",
+                    "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
+                    "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
+                    "dev": true
+                },
+                "http-proxy": {
+                    "version": "1.17.0",
+                    "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
+                    "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
+                    "dev": true,
+                    "requires": {
+                        "eventemitter3": "^3.0.0",
+                        "follow-redirects": "^1.0.0",
+                        "requires-port": "^1.0.0"
+                    }
+                },
+                "is-glob": {
+                    "version": "4.0.1",
+                    "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+                    "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+                    "dev": true,
+                    "requires": {
+                        "is-extglob": "^2.1.1"
+                    }
+                },
+                "lodash": {
+                    "version": "4.17.15",
+                    "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+                    "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+                    "dev": true
+                }
+            }
+        },
+        "http-signature": {
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
+            "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
+            "dev": true,
+            "requires": {
+                "assert-plus": "^1.0.0",
+                "jsprim": "^1.2.2",
+                "sshpk": "^1.7.0"
+            }
+        },
+        "https-browserify": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+            "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=",
+            "dev": true
+        },
+        "https-proxy-agent": {
+            "version": "2.2.1",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
+            "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
+            "dev": true,
+            "requires": {
+                "agent-base": "^4.1.0",
+                "debug": "^3.1.0"
+            },
+            "dependencies": {
+                "agent-base": {
+                    "version": "4.2.1",
+                    "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz",
+                    "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==",
+                    "dev": true,
+                    "requires": {
+                        "es6-promisify": "^5.0.0"
+                    }
+                }
+            }
+        },
+        "husky": {
+            "version": "2.3.0",
+            "resolved": "https://registry.npmjs.org/husky/-/husky-2.3.0.tgz",
+            "integrity": "sha512-A/ZQSEILoq+mQM3yC3RIBSaw1bYXdkKnyyKVSUiJl+iBjVZc5LQEXdGY1ZjrDxC4IzfRPiJ0IqzEQGCN5TQa/A==",
+            "dev": true,
+            "requires": {
+                "cosmiconfig": "^5.2.0",
+                "execa": "^1.0.0",
+                "find-up": "^3.0.0",
+                "get-stdin": "^7.0.0",
+                "is-ci": "^2.0.0",
+                "pkg-dir": "^4.1.0",
+                "please-upgrade-node": "^3.1.1",
+                "read-pkg": "^5.1.1",
+                "run-node": "^1.0.0",
+                "slash": "^3.0.0"
+            },
+            "dependencies": {
+                "find-up": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+                    "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+                    "dev": true,
+                    "requires": {
+                        "locate-path": "^3.0.0"
+                    }
+                },
+                "get-stdin": {
+                    "version": "7.0.0",
+                    "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz",
+                    "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==",
+                    "dev": true
+                },
+                "locate-path": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+                    "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+                    "dev": true,
+                    "requires": {
+                        "p-locate": "^3.0.0",
+                        "path-exists": "^3.0.0"
+                    }
+                },
+                "normalize-package-data": {
+                    "version": "2.5.0",
+                    "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
+                    "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
+                    "dev": true,
+                    "requires": {
+                        "hosted-git-info": "^2.1.4",
+                        "resolve": "^1.10.0",
+                        "semver": "2 || 3 || 4 || 5",
+                        "validate-npm-package-license": "^3.0.1"
+                    }
+                },
+                "p-limit": {
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
+                    "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
+                    "dev": true,
+                    "requires": {
+                        "p-try": "^2.0.0"
+                    }
+                },
+                "p-locate": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+                    "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+                    "dev": true,
+                    "requires": {
+                        "p-limit": "^2.0.0"
+                    }
+                },
+                "p-try": {
+                    "version": "2.2.0",
+                    "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+                    "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+                    "dev": true
+                },
+                "parse-json": {
+                    "version": "4.0.0",
+                    "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+                    "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
+                    "dev": true,
+                    "requires": {
+                        "error-ex": "^1.3.1",
+                        "json-parse-better-errors": "^1.0.1"
+                    }
+                },
+                "path-exists": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+                    "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
+                    "dev": true
+                },
+                "pkg-dir": {
+                    "version": "4.2.0",
+                    "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+                    "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+                    "dev": true,
+                    "requires": {
+                        "find-up": "^4.0.0"
+                    },
+                    "dependencies": {
+                        "find-up": {
+                            "version": "4.0.0",
+                            "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.0.0.tgz",
+                            "integrity": "sha512-zoH7ZWPkRdgwYCDVoQTzqjG8JSPANhtvLhh4KVUHyKnaUJJrNeFmWIkTcNuJmR3GLMEmGYEf2S2bjgx26JTF+Q==",
+                            "dev": true,
+                            "requires": {
+                                "locate-path": "^5.0.0"
+                            }
+                        },
+                        "locate-path": {
+                            "version": "5.0.0",
+                            "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+                            "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+                            "dev": true,
+                            "requires": {
+                                "p-locate": "^4.1.0"
+                            }
+                        },
+                        "p-locate": {
+                            "version": "4.1.0",
+                            "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+                            "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+                            "dev": true,
+                            "requires": {
+                                "p-limit": "^2.2.0"
+                            }
+                        }
+                    }
+                },
+                "read-pkg": {
+                    "version": "5.1.1",
+                    "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.1.1.tgz",
+                    "integrity": "sha512-dFcTLQi6BZ+aFUaICg7er+/usEoqFdQxiEBsEMNGoipenihtxxtdrQuBXvyANCEI8VuUIVYFgeHGx9sLLvim4w==",
+                    "dev": true,
+                    "requires": {
+                        "@types/normalize-package-data": "^2.4.0",
+                        "normalize-package-data": "^2.5.0",
+                        "parse-json": "^4.0.0",
+                        "type-fest": "^0.4.1"
+                    }
+                },
+                "resolve": {
+                    "version": "1.11.0",
+                    "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz",
+                    "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==",
+                    "dev": true,
+                    "requires": {
+                        "path-parse": "^1.0.6"
+                    }
+                },
+                "slash": {
+                    "version": "3.0.0",
+                    "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+                    "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+                    "dev": true
+                }
+            }
         },
         "iconv-lite": {
-          "version": "0.4.24",
-          "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-          "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-          "dev": true,
-          "requires": {
-            "safer-buffer": "2.1.2"
-          }
+            "version": "0.4.23",
+            "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
+            "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
+            "dev": true,
+            "requires": {
+                "safer-buffer": ">= 2.1.2 < 3"
+            }
         },
-        "mime-db": {
-          "version": "1.40.0",
-          "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
-          "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
-          "dev": true
+        "icss-replace-symbols": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
+            "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
+            "dev": true
+        },
+        "icss-utils": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.0.tgz",
+            "integrity": "sha512-3DEun4VOeMvSczifM3F2cKQrDQ5Pj6WKhkOq6HD4QTnDUAq8MQRxy5TX6Sy1iY6WPBe4gQ3p5vTECjbIkglkkQ==",
+            "dev": true,
+            "requires": {
+                "postcss": "^7.0.14"
+            }
         },
-        "mime-types": {
-          "version": "2.1.24",
-          "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
-          "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
-          "dev": true,
-          "requires": {
-            "mime-db": "1.40.0"
-          }
+        "ieee754": {
+            "version": "1.1.13",
+            "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
+            "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==",
+            "dev": true
         },
-        "qs": {
-          "version": "6.7.0",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
-          "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
-          "dev": true
+        "iferr": {
+            "version": "0.1.5",
+            "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
... 22871 lines suppressed ...


[nifi-registry] 14/43: NIFIREG-337 Add automated testing for Postgres 10.x

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 219b57c27be77d900364236d6aa6e6e11ed72c8f
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Thu Oct 17 13:24:29 2019 -0400

    NIFIREG-337 Add automated testing for Postgres 10.x
---
 README.md                                          |  3 +-
 .../src/main/asciidoc/administration-guide.adoc    |  2 +-
 .../registry/db/Postgres10DataSourceFactory.java   | 55 ++++++++++++++++++++++
 nifi-registry-core/pom.xml                         | 13 +++++
 4 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 4999a69..3e97e83 100644
--- a/README.md
+++ b/README.md
@@ -77,7 +77,8 @@ Assuming Docker is running on the system where the build is running, then the fo
 | --------------- | ------------- |
 | All supported   | `mvn verify -Ptest-all-dbs` |
 | H2 (default)    | `mvn verify` |
-| PostgreSQL      | `mvn verify -Dspring.profiles.active=postgres` | 
+| PostgreSQL 9.x  | `mvn verify -Dspring.profiles.active=postgres` | 
+| PostgreSQL 10.x | `mvn verify -Dspring.profiles.active=postgres-10` | 
 | MySQL 5.6       | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-56` |
 | MySQL 5.7       | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-57` |
 | MySQL 8         | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-8`  |
diff --git a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
index 0c6a5dd..90b80d5 100644
--- a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
@@ -1128,7 +1128,7 @@ providing 2 total locations, including `nifi.registry.extension.dir.1`.
 
 The metadata database maintains the knowledge of which buckets exist, which versioned items belong to which buckets, as well as the version history for each item.
 
-Currently, NiFi Registry supports using H2, Postgres 9.x, and MySQL (5.6, 5.7, 8.0) for the relational database engine.
+Currently, NiFi Registry supports using H2, Postgres (9.x, 10.x), and MySQL (5.6, 5.7, 8.0) for the relational database engine.
 
 NOTE: NiFi Registry 0.1.0 only supports H2.
 
diff --git a/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/Postgres10DataSourceFactory.java b/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/Postgres10DataSourceFactory.java
new file mode 100644
index 0000000..23d2f1d
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-test/src/main/java/org/apache/nifi/registry/db/Postgres10DataSourceFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.db;
+
+import org.postgresql.ds.PGSimpleDataSource;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.delegate.DatabaseDelegate;
+import org.testcontainers.jdbc.JdbcDatabaseDelegate;
+
+import javax.annotation.PostConstruct;
+import javax.script.ScriptException;
+import javax.sql.DataSource;
+import java.sql.SQLException;
+
+@Configuration
+@Profile("postgres-10")
+public class Postgres10DataSourceFactory extends TestDataSourceFactory {
+
+    private static final PostgreSQLContainer POSTGRESQL_CONTAINER = new PostgreSQLContainer("postgres:10");
+
+    static {
+        POSTGRESQL_CONTAINER.start();
+    }
+
+    @Override
+    protected DataSource createDataSource() {
+        PGSimpleDataSource dataSource = new PGSimpleDataSource();
+        dataSource.setUrl(POSTGRESQL_CONTAINER.getJdbcUrl());
+        dataSource.setUser(POSTGRESQL_CONTAINER.getUsername());
+        dataSource.setPassword(POSTGRESQL_CONTAINER.getPassword());
+        return dataSource;
+    }
+
+    @PostConstruct
+    public void initDatabase() throws SQLException, ScriptException {
+        DatabaseDelegate databaseDelegate = new JdbcDatabaseDelegate(POSTGRESQL_CONTAINER, "");
+        databaseDelegate.execute("DROP DATABASE test; CREATE DATABASE test;", "", 0, false, true);
+    }
+}
diff --git a/nifi-registry-core/pom.xml b/nifi-registry-core/pom.xml
index b69059e..559eac6 100644
--- a/nifi-registry-core/pom.xml
+++ b/nifi-registry-core/pom.xml
@@ -207,6 +207,19 @@
                                     </systemPropertyVariables>
                                 </configuration>
                             </execution>
+                            <execution>
+                                <id>postgres10-test</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <spring.profiles.active>postgres-10</spring.profiles.active>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
                         </executions>
                     </plugin>
                 </plugins>


[nifi-registry] 34/43: NIFIREG-363 Adds support for Github Actions CI build on Java 8 and Java 11. Does not yet remove travis. And does not yet support the xvfb/chrome portion for jsUnitTests.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 5feb697f0f59a926caf42bae0b87685a7009356d
Author: Joe Witt <jo...@apache.org>
AuthorDate: Thu Feb 20 23:00:43 2020 -0500

    NIFIREG-363 Adds support for Github Actions CI build on Java 8 and Java 11. Does not yet remove travis. And does not yet support the xvfb/chrome portion for jsUnitTests.
    
    Signed-off-by: Pierre Villard <pi...@gmail.com>
    
    This closes #262.
---
 .github/workflows/ci-workflow.yml | 77 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml
new file mode 100644
index 0000000..e9412b1
--- /dev/null
+++ b/.github/workflows/ci-workflow.yml
@@ -0,0 +1,77 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+name: ci-workflow
+
+on: [push, pull_request]
+
+jobs:
+  ubuntu-build:
+
+    timeout-minutes: 90
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        java: [ '1.8', '11' ]
+    name: Ubuntu Build NiFi Registry - JDK${{ matrix.java }}
+
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout@v2
+    - name: Check NPM Cache
+      uses: actions/cache@v1.1.2
+      with:
+        path: ~/.npm
+        key: linux-${{ matrix.java }}-npm-${{ hashFiles('**/package-lock.json') }}
+        restore-keys: |
+          linux-${{ matrix.java }}-npm-
+    - name: Check Maven Com Cache
+      uses: actions/cache@v1.1.2
+      with:
+        path: ~/.m2/repository/com
+        key: linux-${{ matrix.java }}-maven-com-${{ hashFiles('**/pom.xml') }}
+        restore-keys: |
+          linux-${{ matrix.java }}-maven-com-
+    - name: Check Maven Org Cache
+      uses: actions/cache@v1.1.2
+      with:
+        path: ~/.m2/repository/org
+        key: linux-${{ matrix.java }}-maven-org-${{ hashFiles('**/pom.xml') }}
+        restore-keys: |
+          linux-${{ matrix.java }}-maven-org-
+    - name: Check Maven Net Cache
+      uses: actions/cache@v1.1.2
+      with:
+        path: ~/.m2/repository/net
+        key: linux-${{ matrix.java }}-maven-net-${{ hashFiles('**/pom.xml') }}
+        restore-keys: |
+          linux-${{ matrix.java }}-maven-net-
+    - name: Check Maven IO Cache
+      uses: actions/cache@v1.1.2
+      with:
+        path: ~/.m2/repository/io
+        key: linux-${{ matrix.java }}-maven-io-${{ hashFiles('**/pom.xml') }}
+        restore-keys: |
+          linux-${{ matrix.java }}-maven-io-
+    - name: Set up JDK ${{ matrix.java }}
+      uses: actions/setup-java@v1.3.0
+      with:
+        java-version: ${{ matrix.java }}
+    - name: Build with Maven
+      env:
+        MAVEN_OPTS: -Xmx2g -XX:ReservedCodeCacheSize=1g -XX:+UseG1GC -Dorg.slf4j.simpleLogger.defaultLogLevel=WARN
+      run: |
+        mvn -version
+        mvn -T 1C install -B -Pcontrib-check -ntp -ff
+        rm -rf ~/.m2/repository/org/apache/nifi
\ No newline at end of file


[nifi-registry] 33/43: NIFIREG-358 Refactoring proxy authorization to be part of Authorizables

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit ede3143db400f132e239baa727d2e7f2eca92bf4
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Fri Feb 7 12:22:37 2020 -0500

    NIFIREG-358 Refactoring proxy authorization to be part of Authorizables
    
    NIFIREG-358 Catching UntrustedProxyException when asking for authorized resources since it would be considered unauthorized
    
    This closes #258.
    
    Signed-off-by: Kevin Doran <kd...@apache.org>
---
 .../security/authorization/AuthorizerFactory.java  |  12 -
 .../authorization/FrameworkAuthorizer.java         | 189 ----------
 .../authorization/FrameworkManagedAuthorizer.java  |  54 ---
 .../authorization/StandardAuthorizableLookup.java  |  78 +++-
 .../authorization/UntrustedProxyException.java     |  29 ++
 .../authorization/resource/Authorizable.java       |  14 -
 .../resource/ProxyChainAuthorizable.java           | 145 ++++++++
 .../resource/PublicCheckingAuthorizable.java       | 107 ++++++
 .../registry/service/AuthorizationService.java     |   3 +-
 .../service/AuthorizationServiceSpec.groovy        |   3 +-
 .../authorization/TestFrameworkAuthorizer.java     | 278 --------------
 .../TestStandardAuthorizableLookup.java            | 404 +++++++++++++++++++++
 .../authorization/AuthorizationRequest.java        |   5 +
 .../web/mapper/UntrustedProxyExceptionMapper.java  |  48 +++
 .../ResourceAuthorizationFilterSpec.groovy         |   4 +-
 15 files changed, 814 insertions(+), 559 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
index 959e29e..f69ac3c 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
@@ -248,12 +248,8 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
                             try (final ExtensionCloseable extClosable = ExtensionCloseable.withClassLoader(authorizerClassLoader)) {
                                 authorizer.onConfigured(authorizerConfigurationContext);
                             }
-
-                            // wrap the integrity checked Authorizer with the FrameworkAuthorizer
-                            authorizer = createFrameworkAuthorizer(authorizer);
                         }
 
-
                     } catch (AuthorizerFactoryException e) {
                         throw e;
                     } catch (Exception e) {
@@ -427,14 +423,6 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
         return instance;
     }
 
-    private Authorizer createFrameworkAuthorizer(final Authorizer baseAuthorizer) {
-        if (baseAuthorizer instanceof ManagedAuthorizer) {
-            return new FrameworkManagedAuthorizer((ManagedAuthorizer) baseAuthorizer, registryService);
-        } else {
-            return new FrameworkAuthorizer(baseAuthorizer, registryService);
-        }
-    }
-
     private void performMethodInjection(final Object instance, final Class authorizerClass) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
         for (final Method method : authorizerClass.getMethods()) {
             if (method.isAnnotationPresent(AuthorizerContext.class)) {
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/FrameworkAuthorizer.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/FrameworkAuthorizer.java
deleted file mode 100644
index 08fb8f0..0000000
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/FrameworkAuthorizer.java
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.nifi.registry.security.authorization;
-
-import org.apache.nifi.registry.bucket.Bucket;
-import org.apache.nifi.registry.exception.ResourceNotFoundException;
-import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
-import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException;
-import org.apache.nifi.registry.security.authorization.resource.Authorizable;
-import org.apache.nifi.registry.security.authorization.resource.ResourceFactory;
-import org.apache.nifi.registry.security.authorization.resource.ResourceType;
-import org.apache.nifi.registry.security.authorization.user.NiFiUser;
-import org.apache.nifi.registry.security.authorization.user.StandardNiFiUser;
-import org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
-import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
-import org.apache.nifi.registry.service.RegistryService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Objects;
-
-/**
- * Wraps an Authorizer and adds framework level logic for authorizing proxies, public resources, and anything else
- * that needs to be done on top of the regular Authorizer.
- */
-public class FrameworkAuthorizer implements Authorizer {
-
-    public static Logger LOGGER = LoggerFactory.getLogger(FrameworkAuthorizer.class);
-
-    private static final Authorizable PROXY_AUTHORIZABLE = new Authorizable() {
-        @Override
-        public Authorizable getParentAuthorizable() {
-            return null;
-        }
-
-        @Override
-        public Resource getResource() {
-            return ResourceFactory.getProxyResource();
-        }
-    };
-
-    private final Authorizer wrappedAuthorizer;
-    private final RegistryService registryService;
-
-    public FrameworkAuthorizer(final Authorizer wrappedAuthorizer, final RegistryService registryService) {
-        this.wrappedAuthorizer = Objects.requireNonNull(wrappedAuthorizer);
-        this.registryService = Objects.requireNonNull(registryService);
-    }
-
-    @Override
-    public void initialize(final AuthorizerInitializationContext initializationContext) throws SecurityProviderCreationException {
-        wrappedAuthorizer.initialize(initializationContext);
-    }
-
-    @Override
-    public void onConfigured(final AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
-        wrappedAuthorizer.onConfigured(configurationContext);
-    }
-
-    @Override
-    public AuthorizationResult authorize(final AuthorizationRequest request) throws AuthorizationAccessException {
-        final Resource resource = request.getResource();
-        final RequestAction requestAction = request.getAction();
-
-        /**
-         * If the request is for a resource that has been made public and action is READ, then it should automatically be authorized.
-         *
-         * This needs to be checked before the proxy authorizations b/c access to a public resource should always be allowed.
-         */
-
-        final boolean allowPublicAccess = isPublicAccessAllowed(resource, requestAction);
-        if (allowPublicAccess) {
-            if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Authorizing access to public resource '{}'", new Object[]{resource.getIdentifier()});
-            }
-            return AuthorizationResult.approved();
-        }
-
-        /**
-         * Deny an anonymous user access to anything else, they should only have access to publicly readable resources checked above
-         */
-
-        if (request.isAnonymous()) {
-            return AuthorizationResult.denied("Anonymous access is not authorized");
-        }
-
-        /*
-        * If the request has a proxy chain, ensure each identity in the chain is an authorized proxy for the given action.
-        *
-        * The action comes from the original request. For example, if user1 is proxied by proxy1, and it is a WRITE request
-        * to /buckets/12345, then we need to determine if proxy1 is authorized to proxy WRITE requests.
-        */
-
-        final List<String> proxyChainIdentities = request.getProxyIdentities();
-        if (LOGGER.isDebugEnabled()) {
-            LOGGER.debug("Found {} proxy identities", new Object[]{proxyChainIdentities.size()});
-        }
-
-        for (final String proxyIdentity : proxyChainIdentities) {
-            final NiFiUser proxyNiFiUser = createProxyNiFiUser(proxyIdentity);
-            if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Authorizing proxy [{}] for {}", new Object[]{proxyIdentity, requestAction});
-            }
-
-            try {
-                PROXY_AUTHORIZABLE.authorize(wrappedAuthorizer, requestAction, proxyNiFiUser);
-            } catch (final AccessDeniedException e) {
-                final String actionString = requestAction.toString();
-                return AuthorizationResult.denied(String.format("Untrusted proxy [%s] for %s operation.", proxyIdentity, actionString));
-            }
-        }
-
-        /**
-         * All other authorization decisions need to be delegated to the original wrapped Authorizer.
-         */
-
-        return wrappedAuthorizer.authorize(request);
-    }
-
-    /**
-     * Determines if the given Resource is considered public for the action being performed.
-     *
-     * @param resource a Resource being authorized
-     * @param action the action being performed
-     * @return true if the resource is public for the given action, false otherwise
-     */
-    private boolean isPublicAccessAllowed(final Resource resource, final RequestAction action) {
-        if (resource == null || action == null) {
-            return false;
-        }
-
-        final String resourceIdentifier = resource.getIdentifier();
-        if (resourceIdentifier == null || !resourceIdentifier.startsWith(ResourceType.Bucket.getValue() + "/")) {
-            return false;
-        }
-
-        final int lastSlashIndex = resourceIdentifier.lastIndexOf("/");
-        if (lastSlashIndex < 0 || lastSlashIndex >= resourceIdentifier.length() - 1) {
-            return false;
-        }
-
-        final String bucketId = resourceIdentifier.substring(lastSlashIndex + 1);
-        try {
-            final Bucket bucket = registryService.getBucket(bucketId);
-            return bucket.isAllowPublicRead() && action == RequestAction.READ;
-        } catch (ResourceNotFoundException rnfe) {
-            // if not found then we can't determine public access, so return false to delegate to regular authorizer
-            LOGGER.debug("Cannot determine public access, bucket not found with id [{}]", new Object[]{bucketId});
-            return false;
-        } catch (Exception e) {
-            LOGGER.error("Error checking public access to bucket with id [{}]", new Object[]{bucketId}, e);
-            return false;
-        }
-    }
-
-    /**
-     * Creates a NiFiUser for the given proxy identity.
-     *
-     * This is only intended to be used for authorizing the given proxy identity against the /proxy resource, so we
-     * don't need to populate the rest of the info on this user.
-     *
-     * @param proxyIdentity the proxy identity
-     * @return the NiFiUser
-     */
-    private NiFiUser createProxyNiFiUser(final String proxyIdentity) {
-        return new StandardNiFiUser.Builder().identity(proxyIdentity).build();
-    }
-
-    @Override
-    public void preDestruction() throws SecurityProviderDestructionException {
-        wrappedAuthorizer.preDestruction();
-    }
-
-}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/FrameworkManagedAuthorizer.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/FrameworkManagedAuthorizer.java
deleted file mode 100644
index 478482e..0000000
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/FrameworkManagedAuthorizer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.nifi.registry.security.authorization;
-
-import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException;
-import org.apache.nifi.registry.security.authorization.exception.UninheritableAuthorizationsException;
-import org.apache.nifi.registry.service.RegistryService;
-
-/**
- * Similar to FrameworkAuthorizer, but specifically for wrapping a ManagedAuthorizer.
- */
-public class FrameworkManagedAuthorizer extends FrameworkAuthorizer implements ManagedAuthorizer {
-
-    private final ManagedAuthorizer wrappedManagedAuthorizer;
-
-    public FrameworkManagedAuthorizer(final ManagedAuthorizer wrappedManagedAuthorizer, final RegistryService registryService) {
-        super(wrappedManagedAuthorizer, registryService);
-        this.wrappedManagedAuthorizer = wrappedManagedAuthorizer;
-    }
-
-    @Override
-    public String getFingerprint() throws AuthorizationAccessException {
-        return wrappedManagedAuthorizer.getFingerprint();
-    }
-
-    @Override
-    public void inheritFingerprint(final String fingerprint) throws AuthorizationAccessException {
-        wrappedManagedAuthorizer.inheritFingerprint(fingerprint);
-    }
-
-    @Override
-    public void checkInheritability(final String proposedFingerprint) throws AuthorizationAccessException, UninheritableAuthorizationsException {
-        wrappedManagedAuthorizer.checkInheritability(proposedFingerprint);
-    }
-
-    @Override
-    public AccessPolicyProvider getAccessPolicyProvider() {
-        return wrappedManagedAuthorizer.getAccessPolicyProvider();
-    }
-}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java
index 18c2a52..6f68ebe 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/StandardAuthorizableLookup.java
@@ -17,15 +17,22 @@
 package org.apache.nifi.registry.security.authorization;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.bucket.Bucket;
 import org.apache.nifi.registry.exception.ResourceNotFoundException;
 import org.apache.nifi.registry.security.authorization.resource.Authorizable;
 import org.apache.nifi.registry.security.authorization.resource.InheritingAuthorizable;
+import org.apache.nifi.registry.security.authorization.resource.ProxyChainAuthorizable;
+import org.apache.nifi.registry.security.authorization.resource.PublicCheckingAuthorizable;
 import org.apache.nifi.registry.security.authorization.resource.ResourceFactory;
 import org.apache.nifi.registry.security.authorization.resource.ResourceType;
+import org.apache.nifi.registry.service.RegistryService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import java.util.Objects;
+
 @Component
 public class StandardAuthorizableLookup implements AuthorizableLookup {
 
@@ -103,14 +110,21 @@ public class StandardAuthorizableLookup implements AuthorizableLookup {
         }
     };
 
+    private final RegistryService registryService;
+
+    @Autowired
+    public StandardAuthorizableLookup(final RegistryService registryService) {
+        this.registryService = Objects.requireNonNull(registryService);
+    }
+
     @Override
     public Authorizable getActuatorAuthorizable() {
-        return ACTUATOR_AUTHORIZABLE;
+        return new ProxyChainAuthorizable(ACTUATOR_AUTHORIZABLE, PROXY_AUTHORIZABLE, this::isPublicAccessAllowed);
     }
 
     @Override
     public Authorizable getSwaggerAuthorizable() {
-        return SWAGGER_AUTHORIZABLE;
+        return new ProxyChainAuthorizable(SWAGGER_AUTHORIZABLE, PROXY_AUTHORIZABLE, this::isPublicAccessAllowed);
     }
 
     @Override
@@ -120,34 +134,42 @@ public class StandardAuthorizableLookup implements AuthorizableLookup {
 
     @Override
     public Authorizable getTenantsAuthorizable() {
-        return TENANTS_AUTHORIZABLE;
+        return new ProxyChainAuthorizable(TENANTS_AUTHORIZABLE, PROXY_AUTHORIZABLE, this::isPublicAccessAllowed);
     }
 
     @Override
     public Authorizable getPoliciesAuthorizable() {
-        return POLICIES_AUTHORIZABLE;
+        return new ProxyChainAuthorizable(POLICIES_AUTHORIZABLE, PROXY_AUTHORIZABLE, this::isPublicAccessAllowed);
     }
 
     @Override
     public Authorizable getBucketsAuthorizable() {
-        return BUCKETS_AUTHORIZABLE;
+        return new ProxyChainAuthorizable(BUCKETS_AUTHORIZABLE, PROXY_AUTHORIZABLE, this::isPublicAccessAllowed);
     }
 
     @Override
     public Authorizable getBucketAuthorizable(String bucketIdentifier) {
-        // Note - this returns a special Authorizable type that inherits permissions from the parent Authorizable
-        return new InheritingAuthorizable() {
+        // Note - this creates a special Authorizable type that inherits permissions from the parent Authorizable
+        final Authorizable inheritingAuthorizable = new InheritingAuthorizable() {
 
             @Override
             public Authorizable getParentAuthorizable() {
-                return getBucketsAuthorizable();
+                // Use the unwrapped buckets authorizable here so that we don't reauthorize the proxy chain
+                return BUCKETS_AUTHORIZABLE;
             }
 
             @Override
             public Resource getResource() {
                 return ResourceFactory.getBucketResource(bucketIdentifier, "Bucket with ID " + bucketIdentifier);
             }
+
         };
+
+        // Wrap the inheriting Authorizable with logic that first checks if public access is allowed, if not then delegates to the inheriting Authorizable
+        final Authorizable publicCheckingAuthorizable = new PublicCheckingAuthorizable(inheritingAuthorizable, this::isPublicAccessAllowed);
+
+        // Return ProxyChainAuthorizable -> public checking Authorizable -> inheriting Authorizable
+        return new ProxyChainAuthorizable(publicCheckingAuthorizable, PROXY_AUTHORIZABLE, this::isPublicAccessAllowed);
     }
 
     @Override
@@ -217,4 +239,44 @@ public class StandardAuthorizableLookup implements AuthorizableLookup {
         return authorizable;
     }
 
+    /**
+     * Determines if the given Resource is considered public for the action being performed.
+     *
+     * @param resource a Resource being authorized
+     * @param action the action being performed
+     * @return true if the resource is public for the given action, false otherwise
+     */
+    private boolean isPublicAccessAllowed(final Resource resource, final RequestAction action) {
+        if (resource == null || action == null) {
+            return false;
+        }
+
+        if (action != RequestAction.READ) {
+            return false;
+        }
+
+        final String resourceIdentifier = resource.getIdentifier();
+        if (resourceIdentifier == null || !resourceIdentifier.startsWith(ResourceType.Bucket.getValue() + "/")) {
+            return false;
+        }
+
+        final int lastSlashIndex = resourceIdentifier.lastIndexOf("/");
+        if (lastSlashIndex < 0 || lastSlashIndex >= resourceIdentifier.length() - 1) {
+            return false;
+        }
+
+        final String bucketId = resourceIdentifier.substring(lastSlashIndex + 1);
+        try {
+            final Bucket bucket = registryService.getBucket(bucketId);
+            return bucket.isAllowPublicRead();
+        } catch (ResourceNotFoundException rnfe) {
+            // if not found then we can't determine public access, so return false to delegate to regular authorizer
+            logger.debug("Cannot determine public access, bucket not found with id [{}]", new Object[]{bucketId});
+            return false;
+        } catch (Exception e) {
+            logger.error("Error checking public access to bucket with id [{}]", new Object[]{bucketId}, e);
+            return false;
+        }
+    }
+
 }
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/UntrustedProxyException.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/UntrustedProxyException.java
new file mode 100644
index 0000000..fbf1580
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/UntrustedProxyException.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization;
+
+public class UntrustedProxyException extends RuntimeException {
+
+    public UntrustedProxyException(String message) {
+        super(message);
+    }
+
+    public UntrustedProxyException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/Authorizable.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/Authorizable.java
index 04cb469..c461965 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/Authorizable.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/Authorizable.java
@@ -27,9 +27,7 @@ import org.apache.nifi.registry.security.authorization.UserContextKeys;
 import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
 import org.apache.nifi.registry.security.authorization.user.NiFiUser;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 public interface Authorizable {
@@ -95,10 +93,6 @@ public interface Authorizable {
             userContext = null;
         }
 
-        // Note: We don't include the proxy identities here since this is not a direct attempt to access the resource and
-        // we just want to determine if the end user is authorized. The proxy identities will be authorized when calling
-        // Authorizable.authorize() during a direct access attempt for a resource.
-
         final Resource resource = getResource();
         final Resource requestedResource = getRequestedResource();
         final AuthorizationRequest request = new AuthorizationRequest.Builder()
@@ -211,18 +205,10 @@ public interface Authorizable {
             userContext = null;
         }
 
-        final List<String> proxyChain = new ArrayList<>();
-        NiFiUser proxyUser = user.getChain();
-        while (proxyUser  != null) {
-            proxyChain.add(proxyUser.getIdentity());
-            proxyUser = proxyUser.getChain();
-        }
-
         final Resource resource = getResource();
         final Resource requestedResource = getRequestedResource();
         final AuthorizationRequest request = new AuthorizationRequest.Builder()
                 .identity(user.getIdentity())
-                .proxyIdentities(proxyChain)
                 .groups(user.getGroups())
                 .anonymous(user.isAnonymous())
                 .accessAttempt(true)
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ProxyChainAuthorizable.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ProxyChainAuthorizable.java
new file mode 100644
index 0000000..aec8d76
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/ProxyChainAuthorizable.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.resource;
+
+import org.apache.nifi.registry.security.authorization.AuthorizationResult;
+import org.apache.nifi.registry.security.authorization.Authorizer;
+import org.apache.nifi.registry.security.authorization.RequestAction;
+import org.apache.nifi.registry.security.authorization.Resource;
+import org.apache.nifi.registry.security.authorization.UntrustedProxyException;
+import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
+import org.apache.nifi.registry.security.authorization.user.NiFiUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * Authorizable that wraps another Authorizable and applies logic for authorizing the proxy chain, unless the resource
+ * allows public access, which then skips authorizing the proxy chain.
+ */
+public class ProxyChainAuthorizable implements Authorizable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ProxyChainAuthorizable.class);
+
+    private final Authorizable wrappedAuthorizable;
+    private final Authorizable proxyAuthorizable;
+    private final BiFunction<Resource,RequestAction,Boolean> publicResourceCheck;
+
+    public ProxyChainAuthorizable(final Authorizable wrappedAuthorizable,
+                                  final Authorizable proxyAuthorizable,
+                                  final BiFunction<Resource,RequestAction,Boolean> publicResourceCheck) {
+        this.wrappedAuthorizable = Objects.requireNonNull(wrappedAuthorizable);
+        this.proxyAuthorizable = Objects.requireNonNull(proxyAuthorizable);
+        this.publicResourceCheck = Objects.requireNonNull(publicResourceCheck);
+    }
+
+    @Override
+    public Authorizable getParentAuthorizable() {
+        if (wrappedAuthorizable.getParentAuthorizable() == null) {
+            return null;
+        } else {
+            final Authorizable parentAuthorizable = wrappedAuthorizable.getParentAuthorizable();
+            return new ProxyChainAuthorizable(parentAuthorizable, proxyAuthorizable, publicResourceCheck);
+        }
+    }
+
+    @Override
+    public Resource getResource() {
+        return wrappedAuthorizable.getResource();
+    }
+
+    @Override
+    public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user,
+                                                  final Map<String, String> resourceContext) {
+        final Resource requestResource = wrappedAuthorizable.getRequestedResource();
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Requested resource is {}", new Object[]{requestResource.getIdentifier()});
+        }
+
+        // if public access is allowed then we want to skip proxy authorization so just return
+        final Boolean isPublicAccessAllowed = publicResourceCheck.apply(requestResource, action);
+        if (isPublicAccessAllowed) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Proxy chain will not be checked, public access is allowed for {} on {}",
+                        new Object[]{action.toString(), requestResource.getIdentifier()});
+            }
+            return AuthorizationResult.approved();
+        }
+
+        // otherwise public access is not allowed so check the proxy chain for the given action
+        NiFiUser proxyUser = user.getChain();
+        while (proxyUser  != null) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Checking proxy [{}] for {}", new Object[]{proxyUser, action});
+            }
+
+            // if the proxy is denied then break out of the loop and return a denied result
+            final AuthorizationResult proxyAuthorizationResult = proxyAuthorizable.checkAuthorization(authorizer, action, proxyUser);
+            if (proxyAuthorizationResult.getResult() == AuthorizationResult.Result.Denied) {
+                final String deniedMessage = String.format("Untrusted proxy [%s] for %s operation.", proxyUser.getIdentity(), action.toString());
+                return AuthorizationResult.denied(deniedMessage);
+            }
+
+            proxyUser = proxyUser.getChain();
+        }
+
+        // at this point the proxy chain was approved so continue to check the original Authorizable
+        return wrappedAuthorizable.checkAuthorization(authorizer, action, user, resourceContext);
+    }
+
+    @Override
+    public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user,
+                          final Map<String, String> resourceContext) throws AccessDeniedException {
+        final Resource requestResource = wrappedAuthorizable.getRequestedResource();
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Requested resource is {}", new Object[]{requestResource.getIdentifier()});
+        }
+
+        // if public access is allowed then we want to skip proxy authorization so just return
+        final Boolean isPublicAccessAllowed = publicResourceCheck.apply(requestResource, action);
+        if (isPublicAccessAllowed) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Proxy chain will not be authorized, public access is allowed for {} on {}",
+                        new Object[]{action.toString(), requestResource.getIdentifier()});
+            }
+            return;
+        }
+
+        // otherwise public access is not allowed so authorize proxy chain for the given action
+        NiFiUser proxyUser = user.getChain();
+        while (proxyUser  != null) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Authorizing proxy [{}] for {}", new Object[]{proxyUser, action});
+            }
+
+            try {
+                proxyAuthorizable.authorize(authorizer, action, proxyUser);
+            } catch (final AccessDeniedException e) {
+                final String actionString = action.toString();
+                throw new UntrustedProxyException(String.format("Untrusted proxy [%s] for %s operation.", proxyUser.getIdentity(), actionString));
+            }
+            proxyUser = proxyUser.getChain();
+        }
+
+        // at this point the proxy chain was authorized so continue to authorize the original Authorizable
+        wrappedAuthorizable.authorize(authorizer, action, user, resourceContext);
+    }
+
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/PublicCheckingAuthorizable.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/PublicCheckingAuthorizable.java
new file mode 100644
index 0000000..7cacb59
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/resource/PublicCheckingAuthorizable.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.resource;
+
+import org.apache.nifi.registry.security.authorization.AuthorizationResult;
+import org.apache.nifi.registry.security.authorization.Authorizer;
+import org.apache.nifi.registry.security.authorization.RequestAction;
+import org.apache.nifi.registry.security.authorization.Resource;
+import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
+import org.apache.nifi.registry.security.authorization.user.NiFiUser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * Authorizable that first checks if public access is allowed for the resource and action. If it is then it short-circuits
+ * and returns approved, otherwise it continues and delegates to the wrapped Authorizable.
+ */
+public class PublicCheckingAuthorizable implements Authorizable {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PublicCheckingAuthorizable.class);
+
+    private final Authorizable wrappedAuthorizable;
+    private final BiFunction<Resource, RequestAction,Boolean> publicResourceCheck;
+
+    public PublicCheckingAuthorizable(final Authorizable wrappedAuthorizable,
+                                      final BiFunction<Resource,RequestAction,Boolean> publicResourceCheck) {
+        this.wrappedAuthorizable = Objects.requireNonNull(wrappedAuthorizable);
+        this.publicResourceCheck = Objects.requireNonNull(publicResourceCheck);
+    }
+
+    @Override
+    public Authorizable getParentAuthorizable() {
+        return wrappedAuthorizable.getParentAuthorizable();
+    }
+
+    @Override
+    public Resource getResource() {
+        return wrappedAuthorizable.getResource();
+    }
+
+    @Override
+    public AuthorizationResult checkAuthorization(final Authorizer authorizer, final RequestAction action, final NiFiUser user,
+                                                  final Map<String, String> resourceContext) {
+        final Resource resource = getResource();
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Requested resource is {}", new Object[]{resource.getIdentifier()});
+        }
+
+        // if public access is allowed then return approved
+        final Boolean isPublicAccessAllowed = publicResourceCheck.apply(resource, action);
+        if(isPublicAccessAllowed) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Public access is allowed for {}", new Object[]{resource.getIdentifier()});
+            }
+            return AuthorizationResult.approved();
+        }
+
+        // otherwise delegate to the original inheriting authorizable
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Delegating to inheriting authorizable for {}", new Object[]{resource.getIdentifier()});
+        }
+        return wrappedAuthorizable.checkAuthorization(authorizer, action, user, resourceContext);
+    }
+
+    @Override
+    public void authorize(final Authorizer authorizer, final RequestAction action, final NiFiUser user,
+                          final Map<String, String> resourceContext) throws AccessDeniedException {
+        final Resource resource = getResource();
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Requested resource is {}", new Object[]{resource.getIdentifier()});
+        }
+
+        // if public access is allowed then skip authorization and return
+        final Boolean isPublicAccessAllowed = publicResourceCheck.apply(resource, action);
+        if(isPublicAccessAllowed) {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Public access is allowed for {}", new Object[]{resource.getIdentifier()});
+            }
+            return;
+        }
+
+        // otherwise delegate to the original authorizable
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Delegating to inheriting authorizable for {}", new Object[]{resource.getIdentifier()});
+        }
+
+        wrappedAuthorizable.authorize(authorizer, action, user, resourceContext);
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
index 5190b64..9f82f0b 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/AuthorizationService.java
@@ -37,6 +37,7 @@ import org.apache.nifi.registry.security.authorization.ConfigurableUserGroupProv
 import org.apache.nifi.registry.security.authorization.Group;
 import org.apache.nifi.registry.security.authorization.ManagedAuthorizer;
 import org.apache.nifi.registry.security.authorization.RequestAction;
+import org.apache.nifi.registry.security.authorization.UntrustedProxyException;
 import org.apache.nifi.registry.security.authorization.UserAndGroups;
 import org.apache.nifi.registry.security.authorization.UserGroupProvider;
 import org.apache.nifi.registry.security.authorization.UserGroupProviderInitializationContext;
@@ -454,7 +455,7 @@ public class AuthorizationService {
                                         .getAuthorizableByResource(resource.getIdentifier())
                                         .authorize(authorizer, actionType, NiFiUserUtils.getNiFiUser());
                                 return true;
-                            } catch (AccessDeniedException e) {
+                            } catch (AccessDeniedException | UntrustedProxyException e) {
                                 return false;
                             }
                         })
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy b/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy
index f47e7ce..508f3e3 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy
+++ b/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/service/AuthorizationServiceSpec.groovy
@@ -40,8 +40,7 @@ class AuthorizationServiceSpec extends Specification {
     def setup() {
         accessPolicyProvider.getUserGroupProvider() >> userGroupProvider
         def standardAuthorizer = new StandardManagedAuthorizer(accessPolicyProvider, userGroupProvider)
-        def frameworkAuthorizer = new FrameworkManagedAuthorizer(standardAuthorizer, registryService)
-        authorizationService = new AuthorizationService(authorizableLookup, frameworkAuthorizer, registryService)
+        authorizationService = new AuthorizationService(authorizableLookup, standardAuthorizer, registryService)
     }
 
     // ----- User tests -------------------------------------------------------
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/TestFrameworkAuthorizer.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/TestFrameworkAuthorizer.java
deleted file mode 100644
index 2cc03f8..0000000
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/TestFrameworkAuthorizer.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package org.apache.nifi.registry.security.authorization;
-
-import org.apache.nifi.registry.bucket.Bucket;
-import org.apache.nifi.registry.security.authorization.resource.ResourceFactory;
-import org.apache.nifi.registry.service.RegistryService;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-
-import java.util.Arrays;
-import java.util.UUID;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class TestFrameworkAuthorizer {
-
-    private Authorizer frameworkAuthorizer;
-    private Authorizer wrappedAuthorizer;
-    private RegistryService registryService;
-
-    private Bucket bucketPublic;
-    private Bucket bucketNotPublic;
-
-    @Before
-    public void setup() {
-        wrappedAuthorizer = mock(Authorizer.class);
-        registryService = mock(RegistryService.class);
-        frameworkAuthorizer = new FrameworkAuthorizer(wrappedAuthorizer, registryService);
-
-        bucketPublic = new Bucket();
-        bucketPublic.setIdentifier(UUID.randomUUID().toString());
-        bucketPublic.setName("Public Bucket");
-        bucketPublic.setAllowPublicRead(true);
-
-        bucketNotPublic = new Bucket();
-        bucketNotPublic.setIdentifier(UUID.randomUUID().toString());
-        bucketNotPublic.setName("Non Public Bucket");
-        bucketNotPublic.setAllowPublicRead(false);
-
-        when(registryService.getBucket(bucketPublic.getIdentifier())).thenReturn(bucketPublic);
-        when(registryService.getBucket(bucketNotPublic.getIdentifier())).thenReturn(bucketNotPublic);
-    }
-
-    @Test
-    public void testReadPublicBucketWhenAnonymous() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketPublic.getIdentifier(), bucketPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.READ)
-                .accessAttempt(true)
-                .identity("anonymous")
-                .anonymous(true)
-                .build();
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Approved, result.getResult());
-
-        // should never make it to wrapped authorizer
-        verify(wrappedAuthorizer, times(0)).authorize(any(AuthorizationRequest.class));
-    }
-
-    @Test
-    public void testReadNonPublicBucketWhenAnonymous() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketNotPublic.getIdentifier(), bucketNotPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.READ)
-                .accessAttempt(true)
-                .identity("anonymous")
-                .anonymous(true)
-                .build();
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
-
-        // should be denied before making it to the wrapped authorizer since the user is anonymous
-        verify(wrappedAuthorizer, times(0)).authorize(any(AuthorizationRequest.class));
-    }
-
-    @Test
-    public void testWritePublicBucketWhenAnonymous() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketPublic.getIdentifier(), bucketPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.WRITE)
-                .accessAttempt(true)
-                .identity("anonymous")
-                .anonymous(true)
-                .build();
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
-
-        // should be denied before making it to wrapped authorizer since request is anonymous
-        verify(wrappedAuthorizer, times(0)).authorize(any(AuthorizationRequest.class));
-    }
-
-    @Test
-    public void testReadPublicBucketWhenNotAnonymous() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketPublic.getIdentifier(), bucketPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.READ)
-                .accessAttempt(true)
-                .identity("user1")
-                .anonymous(false)
-                .proxyIdentities(Arrays.asList("proxy1", "proxy2"))
-                .build();
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Approved, result.getResult());
-
-        // should never make it to wrapped authorizer
-        verify(wrappedAuthorizer, times(0)).authorize(any(AuthorizationRequest.class));
-    }
-
-    @Test
-    public void testReadNonPublicBucketWhenNotAnonymousAndAuthorizedProxies() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketNotPublic.getIdentifier(), bucketNotPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.READ)
-                .accessAttempt(true)
-                .identity("user1")
-                .anonymous(false)
-                .proxyIdentities(Arrays.asList("proxy1", "proxy2"))
-                .build();
-
-        // since the bucket is not public it will fall through to the wrapped authorizer
-        when(wrappedAuthorizer.authorize(any(AuthorizationRequest.class)))
-                .thenReturn(AuthorizationResult.approved());
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Approved, result.getResult());
-
-        // should make 3 calls to the wrapped authorizer to authorize user1, proxy1, proxy2
-        verify(wrappedAuthorizer, times(3)).authorize(any(AuthorizationRequest.class));
-    }
-
-    @Test
-    public void testReadNonPublicBucketWhenNotAnonymousAndUnauthorizedProxy() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketNotPublic.getIdentifier(), bucketNotPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.READ)
-                .accessAttempt(true)
-                .identity("user1")
-                .anonymous(false)
-                .proxyIdentities(Arrays.asList("proxy1", "proxy2"))
-                .build();
-
-        // since the bucket is not public and the user is not anonymous, it will continue to proxy authorization
-
-        // simulate the first proxy being authorized for READ actions
-        final AuthorizationRequestMatcher proxy1Matcher = new AuthorizationRequestMatcher(
-                "proxy1", ResourceFactory.getProxyResource(), request.getAction());
-        when(wrappedAuthorizer.authorize(argThat(proxy1Matcher))).thenReturn(AuthorizationResult.approved());
-
-        // simulate the second proxy being unauthorized for READ actions
-        final AuthorizationRequestMatcher proxy2Matcher = new AuthorizationRequestMatcher(
-                "proxy2", ResourceFactory.getProxyResource(), request.getAction());
-        when(wrappedAuthorizer.authorize(argThat(proxy2Matcher))).thenReturn(AuthorizationResult.denied("denied"));
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
-
-        // should make 2 calls to the wrapped authorizer for the two proxies
-        verify(wrappedAuthorizer, times(2)).authorize(any(AuthorizationRequest.class));
-    }
-
-    @Test
-    public void testReadNonPublicBucketWhenNotAnonymousAndUnauthorizedEndUser() {
-        final Resource resource = ResourceFactory.getBucketResource(bucketNotPublic.getIdentifier(), bucketNotPublic.getName());
-
-        final AuthorizationRequest request = new AuthorizationRequest.Builder()
-                .resource(resource)
-                .requestedResource(resource)
-                .action(RequestAction.READ)
-                .accessAttempt(true)
-                .identity("user1")
-                .anonymous(false)
-                .proxyIdentities(Arrays.asList("proxy1", "proxy2"))
-                .build();
-
-        // since the bucket is not public and the user is not anonymous, it will continue to proxy authorization
-
-        // simulate the first proxy being authorized for READ actions
-        final AuthorizationRequestMatcher proxy1Matcher = new AuthorizationRequestMatcher(
-                "proxy1", ResourceFactory.getProxyResource(), request.getAction());
-        when(wrappedAuthorizer.authorize(argThat(proxy1Matcher))).thenReturn(AuthorizationResult.approved());
-
-        // simulate the second proxy being authorized for READ actions
-        final AuthorizationRequestMatcher proxy2Matcher = new AuthorizationRequestMatcher(
-                "proxy2", ResourceFactory.getProxyResource(), request.getAction());
-        when(wrappedAuthorizer.authorize(argThat(proxy2Matcher))).thenReturn(AuthorizationResult.approved());
-
-        // simulate the end user being unauthorized for READ actions
-        final AuthorizationRequestMatcher user1Matcher = new AuthorizationRequestMatcher(
-                "user1", resource, request.getAction());
-        when(wrappedAuthorizer.authorize(argThat(user1Matcher))).thenReturn(AuthorizationResult.denied("denied"));
-
-        final AuthorizationResult result = frameworkAuthorizer.authorize(request);
-        assertNotNull(result);
-        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
-
-        // should make 3 calls to the wrapped authorizer for the two proxies and end user
-        verify(wrappedAuthorizer, times(3)).authorize(any(AuthorizationRequest.class));
-    }
-
-
-    /**
-     * Matcher for matching Authorization requests.
-     */
-    private static class AuthorizationRequestMatcher implements ArgumentMatcher<AuthorizationRequest> {
-
-        private final String identity;
-        private final Resource resource;
-        private final RequestAction action;
-
-        public AuthorizationRequestMatcher(final String identity, final Resource resource, final RequestAction action) {
-            this.identity = identity;
-            this.resource = resource;
-            this.action = action;
-        }
-
-        @Override
-        public boolean matches(final AuthorizationRequest request) {
-            if (request == null) {
-                return false;
-            }
-
-            return identity.equals(request.getIdentity())
-                    && resource.getIdentifier().equals(request.getResource().getIdentifier())
-                    && action == request.getAction();
-        }
-    }
-}
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/TestStandardAuthorizableLookup.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/TestStandardAuthorizableLookup.java
new file mode 100644
index 0000000..2804ac7
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/security/authorization/TestStandardAuthorizableLookup.java
@@ -0,0 +1,404 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization;
+
+import org.apache.nifi.registry.bucket.Bucket;
+import org.apache.nifi.registry.security.authorization.exception.AccessDeniedException;
+import org.apache.nifi.registry.security.authorization.resource.Authorizable;
+import org.apache.nifi.registry.security.authorization.resource.ResourceFactory;
+import org.apache.nifi.registry.security.authorization.user.NiFiUser;
+import org.apache.nifi.registry.security.authorization.user.StandardNiFiUser;
+import org.apache.nifi.registry.service.RegistryService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+
+import java.util.UUID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class TestStandardAuthorizableLookup {
+
+    private static final NiFiUser USER_NO_PROXY_CHAIN = new StandardNiFiUser.Builder()
+            .identity("user1")
+            .build();
+
+    private static final NiFiUser USER_WITH_PROXY_CHAIN = new StandardNiFiUser.Builder()
+            .identity("user1")
+            .chain(new StandardNiFiUser.Builder().identity("CN=localhost, OU=NIFI").build())
+            .build();
+
+    private Authorizer authorizer;
+    private RegistryService registryService;
+    private AuthorizableLookup authorizableLookup;
+
+    private Bucket bucketPublic;
+    private Bucket bucketNotPublic;
+
+    @Before
+    public void setup() {
+        authorizer = mock(Authorizer.class);
+        registryService = mock(RegistryService.class);
+        authorizableLookup = new StandardAuthorizableLookup(registryService);
+
+        bucketPublic = new Bucket();
+        bucketPublic.setIdentifier(UUID.randomUUID().toString());
+        bucketPublic.setName("Public Bucket");
+        bucketPublic.setAllowPublicRead(true);
+
+        bucketNotPublic = new Bucket();
+        bucketNotPublic.setIdentifier(UUID.randomUUID().toString());
+        bucketNotPublic.setName("Non Public Bucket");
+        bucketNotPublic.setAllowPublicRead(false);
+
+        when(registryService.getBucket(bucketPublic.getIdentifier())).thenReturn(bucketPublic);
+        when(registryService.getBucket(bucketNotPublic.getIdentifier())).thenReturn(bucketNotPublic);
+    }
+
+    // Test check method for Bucket Authorizable
+
+    @Test
+    public void testCheckReadPublicBucketWithNoProxyChain() {
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        final AuthorizationResult result = bucketAuthorizable.checkAuthorization(authorizer, RequestAction.READ, USER_NO_PROXY_CHAIN);
+        assertNotNull(result);
+        assertEquals(AuthorizationResult.Result.Approved, result.getResult());
+
+        // Should never call authorizer because resource is public
+        verify(authorizer, times(0)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testCheckReadPublicBucketWithProxyChain() {
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        final AuthorizationResult result = bucketAuthorizable.checkAuthorization(authorizer, RequestAction.READ, USER_WITH_PROXY_CHAIN);
+        assertNotNull(result);
+        assertEquals(AuthorizationResult.Result.Approved, result.getResult());
+
+        // Should never call authorizer because resource is public
+        verify(authorizer, times(0)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testCheckWritePublicBucketWithUnauthorizedUserAndNoProxyChain() {
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to the specific bucket
+        final AuthorizationRequest expectedBucketAuthorizationRequest = getBucketAuthorizationRequest(
+                bucketPublic.getIdentifier(), action, USER_NO_PROXY_CHAIN);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // second request will go to parent of /buckets
+        final AuthorizationRequest expectedBucketsAuthorizationRequest = getBucketsAuthorizationRequest(action, USER_NO_PROXY_CHAIN);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketsAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // should reach authorizer and return denied
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        final AuthorizationResult result = bucketAuthorizable.checkAuthorization(authorizer, action, USER_NO_PROXY_CHAIN);
+        assertNotNull(result);
+        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
+
+        // Should call authorizer twice for specific bucket and top-level /buckets
+        verify(authorizer, times(2)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testCheckWritePublicBucketWithUnauthorizedProxyChain() {
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to authorize the proxy
+        final AuthorizationRequest expectedProxyAuthorizationRequest = getProxyAuthorizationRequest(action, USER_WITH_PROXY_CHAIN.getChain());
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedProxyAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // the authorization of the proxy chain should return denied
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        final AuthorizationResult result = bucketAuthorizable.checkAuthorization(authorizer, action, USER_WITH_PROXY_CHAIN);
+        assertNotNull(result);
+        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
+
+        // Should never call authorizer once for /proxy and then return denied
+        verify(authorizer, times(1)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testCheckWritePublicBucketWithUnauthorizedUserAndAuthorizedProxyChain() {
+        final NiFiUser user = USER_WITH_PROXY_CHAIN;
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to authorize the proxy
+        final AuthorizationRequest expectedProxyAuthorizationRequest = getProxyAuthorizationRequest(action, user.getChain());
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedProxyAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.approved());
+
+        // second request will be to the specific bucket
+        final AuthorizationRequest expectedBucketAuthorizationRequest = getBucketAuthorizationRequest(
+                bucketPublic.getIdentifier(), action, user);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // third request will go to parent of /buckets
+        final AuthorizationRequest expectedBucketsAuthorizationRequest = getBucketsAuthorizationRequest(action, user);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketsAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // the authorization of the proxy chain should return denied
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        final AuthorizationResult result = bucketAuthorizable.checkAuthorization(authorizer, action, user);
+        assertNotNull(result);
+        assertEquals(AuthorizationResult.Result.Denied, result.getResult());
+
+        // Should call authorizer three time for /proxy, /bucket/{id}, and /buckets
+        verify(authorizer, times(3)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testCheckWritePublicBucketWithAuthorizedUserAndAuthorizedProxyChain() {
+        final NiFiUser user = USER_WITH_PROXY_CHAIN;
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to authorize the proxy
+        final AuthorizationRequest expectedProxyAuthorizationRequest = getProxyAuthorizationRequest(action, user.getChain());
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedProxyAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.approved());
+
+        // second request will be to the specific bucket
+        final AuthorizationRequest expectedBucketAuthorizationRequest = getBucketAuthorizationRequest(
+                bucketPublic.getIdentifier(), action, user);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.approved());
+
+        // the authorization should all return approved
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        final AuthorizationResult result = bucketAuthorizable.checkAuthorization(authorizer, action, user);
+        assertNotNull(result);
+        assertEquals(AuthorizationResult.Result.Approved, result.getResult());
+
+        // Should call authorizer two times for /proxy and /bucket/{id}
+        verify(authorizer, times(2)).authorize(any(AuthorizationRequest.class));
+    }
+
+    // Test authorize method for Bucket Authorizable
+
+    @Test
+    public void testAuthorizeReadPublicBucketWithNoProxyChain() {
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        bucketAuthorizable.authorize(authorizer, RequestAction.READ, USER_NO_PROXY_CHAIN);
+
+        // Should never call authorizer because resource is public
+        verify(authorizer, times(0)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testAuthorizeReadPublicBucketWithProxyChain() {
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        bucketAuthorizable.authorize(authorizer, RequestAction.READ, USER_WITH_PROXY_CHAIN);
+
+        // Should never call authorizer because resource is public
+        verify(authorizer, times(0)).authorize(any(AuthorizationRequest.class));
+    }
+
+    @Test
+    public void testAuthorizeWritePublicBucketWithUnauthorizedUserAndNoProxyChain() {
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to the specific bucket
+        final AuthorizationRequest expectedBucketAuthorizationRequest = getBucketAuthorizationRequest(
+                bucketPublic.getIdentifier(), action, USER_NO_PROXY_CHAIN);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // second request will go to parent of /buckets
+        final AuthorizationRequest expectedBucketsAuthorizationRequest = getBucketsAuthorizationRequest(action, USER_NO_PROXY_CHAIN);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketsAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // should reach authorizer and throw access denied
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        try {
+            bucketAuthorizable.authorize(authorizer, action, USER_NO_PROXY_CHAIN);
+            Assert.fail("Should have thrown exception");
+        } catch (AccessDeniedException e) {
+            // Should never call authorizer twice for specific bucket and top-level /buckets
+            verify(authorizer, times(2)).authorize(any(AuthorizationRequest.class));
+        }
+    }
+
+    @Test
+    public void testAuthorizeWritePublicBucketWithUnauthorizedProxyChain() {
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to authorize the proxy
+        final AuthorizationRequest expectedProxyAuthorizationRequest = getProxyAuthorizationRequest(action, USER_WITH_PROXY_CHAIN.getChain());
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedProxyAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // the authorization of the proxy chain should throw UntrustedProxyException
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        try {
+            bucketAuthorizable.authorize(authorizer, action, USER_WITH_PROXY_CHAIN);
+            Assert.fail("Should have thrown exception");
+        } catch (UntrustedProxyException e) {
+            // Should call authorizer once for /proxy and then throw exception
+            verify(authorizer, times(1)).authorize(any(AuthorizationRequest.class));
+        }
+    }
+
+    @Test
+    public void testAuthorizeWritePublicBucketWithUnauthorizedUserAndAuthorizedProxyChain() {
+        final NiFiUser user = USER_WITH_PROXY_CHAIN;
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to authorize the proxy
+        final AuthorizationRequest expectedProxyAuthorizationRequest = getProxyAuthorizationRequest(action, user.getChain());
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedProxyAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.approved());
+
+        // second request will be to the specific bucket
+        final AuthorizationRequest expectedBucketAuthorizationRequest = getBucketAuthorizationRequest(
+                bucketPublic.getIdentifier(), action, user);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // third request will go to parent of /buckets
+        final AuthorizationRequest expectedBucketsAuthorizationRequest = getBucketsAuthorizationRequest(action, user);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketsAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.denied());
+
+        // the authorization of the proxy chain should throw UntrustedProxyException
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        try {
+            bucketAuthorizable.authorize(authorizer, action, user);
+            Assert.fail("Should have thrown exception");
+        } catch (AccessDeniedException e) {
+            // Should call authorizer three times for /proxy, /bucket/{id}, and /buckets
+            verify(authorizer, times(3)).authorize(any(AuthorizationRequest.class));
+        }
+    }
+
+    @Test
+    public void testAuthorizeWritePublicBucketWithAuthorizedUserAndAuthorizedProxyChain() {
+        final NiFiUser user = USER_WITH_PROXY_CHAIN;
+        final RequestAction action = RequestAction.WRITE;
+
+        // first request will be to authorize the proxy
+        final AuthorizationRequest expectedProxyAuthorizationRequest = getProxyAuthorizationRequest(action, user.getChain());
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedProxyAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.approved());
+
+        // second request will be to the specific bucket
+        final AuthorizationRequest expectedBucketAuthorizationRequest = getBucketAuthorizationRequest(
+                bucketPublic.getIdentifier(), action, user);
+
+        when(authorizer.authorize(argThat(new AuthorizationRequestMatcher(expectedBucketAuthorizationRequest))))
+                .thenReturn(AuthorizationResult.approved());
+
+        // the authorization should all return approved so no exception
+        final Authorizable bucketAuthorizable = authorizableLookup.getBucketAuthorizable(bucketPublic.getIdentifier());
+        bucketAuthorizable.authorize(authorizer, action, user);
+
+        // Should call authorizer two times for /proxy and /bucket/{id}
+        verify(authorizer, times(2)).authorize(any(AuthorizationRequest.class));
+    }
+
+    private AuthorizationRequest getBucketAuthorizationRequest(final String bucketIdentifier, final RequestAction action, final NiFiUser user) {
+        return new AuthorizationRequest.Builder()
+                .resource(ResourceFactory.getBucketResource(bucketIdentifier, bucketIdentifier))
+                .action(action)
+                .identity(user.getIdentity())
+                .accessAttempt(true)
+                .anonymous(false)
+                .build();
+    }
+
+    private AuthorizationRequest getBucketsAuthorizationRequest(final RequestAction action, final NiFiUser user) {
+        return new AuthorizationRequest.Builder()
+                .resource(ResourceFactory.getBucketsResource())
+                .action(action)
+                .identity(user.getIdentity())
+                .accessAttempt(true)
+                .anonymous(false)
+                .build();
+    }
+
+    private AuthorizationRequest getProxyAuthorizationRequest(final RequestAction action, final NiFiUser user) {
+        return new AuthorizationRequest.Builder()
+                .resource(ResourceFactory.getProxyResource())
+                .action(action)
+                .identity(user.getIdentity())
+                .accessAttempt(true)
+                .anonymous(false)
+                .build();
+    }
+
+    /**
+     * ArugmentMatcher for AuthorizationRequest.
+     */
+    private static class AuthorizationRequestMatcher implements ArgumentMatcher<AuthorizationRequest> {
+
+        private final AuthorizationRequest expectedAuthorizationRequest;
+
+        public AuthorizationRequestMatcher(final AuthorizationRequest expectedAuthorizationRequest) {
+            this.expectedAuthorizationRequest = expectedAuthorizationRequest;
+        }
+
+        @Override
+        public boolean matches(final AuthorizationRequest authorizationRequest) {
+            if (authorizationRequest == null) {
+                return false;
+            }
+
+            final String requestResourceId = authorizationRequest.getResource().getIdentifier();
+            final String expectedResourceId = expectedAuthorizationRequest.getResource().getIdentifier();
+
+            final String requestAction = authorizationRequest.getAction().toString();
+            final String expectedAction = expectedAuthorizationRequest.getAction().toString();
+
+            final String requestUserIdentity = authorizationRequest.getIdentity();
+            final String expectedUserIdentity = authorizationRequest.getIdentity();
+
+            return requestResourceId.equals(expectedResourceId)
+                    && requestAction.equals(expectedAction)
+                    && requestUserIdentity.equals(expectedUserIdentity);
+        }
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizationRequest.java b/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizationRequest.java
index 56b7b45..3e832fa 100644
--- a/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizationRequest.java
+++ b/nifi-registry-core/nifi-registry-security-api/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizationRequest.java
@@ -109,6 +109,8 @@ public class AuthorizationRequest {
      * The identities in the proxy chain for the request. Will be empty if the request was not proxied.
      *
      * @return The identities in the proxy chain
+     *
+     * @deprecated no longer populated
      */
     public List<String> getProxyIdentities() {
         return proxyIdentities;
@@ -210,6 +212,9 @@ public class AuthorizationRequest {
             return this;
         }
 
+        /**
+         * @deprecated no longer populated by the framework
+         */
         public Builder proxyIdentities(final List<String> proxyIdentities) {
             this.proxyIdentities = proxyIdentities;
             return this;
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/mapper/UntrustedProxyExceptionMapper.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/mapper/UntrustedProxyExceptionMapper.java
new file mode 100644
index 0000000..453dbd5
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/mapper/UntrustedProxyExceptionMapper.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.web.mapper;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.security.authorization.UntrustedProxyException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.ws.rs.core.Response;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+/**
+ * Maps an UntrustedProxyException to a FORBIDDEN response.
+ */
+@Component
+@Provider
+public class UntrustedProxyExceptionMapper implements ExceptionMapper<UntrustedProxyException> {
+
+    private static Logger LOGGER = LoggerFactory.getLogger(UntrustedProxyException.class);
+
+    @Override
+    public Response toResponse(final UntrustedProxyException exception) {
+        LOGGER.info("{}. Returning {} response.", exception, Response.Status.FORBIDDEN);
+        LOGGER.debug(StringUtils.EMPTY, exception);
+
+        return Response.status(Response.Status.FORBIDDEN)
+                .entity(exception.getMessage())
+                .type("text/plain")
+                .build();
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-web-api/src/test/groovy/org/apache/nifi/registry/security/authorization/ResourceAuthorizationFilterSpec.groovy b/nifi-registry-core/nifi-registry-web-api/src/test/groovy/org/apache/nifi/registry/security/authorization/ResourceAuthorizationFilterSpec.groovy
index e27dfbe..806f73c 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/test/groovy/org/apache/nifi/registry/security/authorization/ResourceAuthorizationFilterSpec.groovy
+++ b/nifi-registry-core/nifi-registry-web-api/src/test/groovy/org/apache/nifi/registry/security/authorization/ResourceAuthorizationFilterSpec.groovy
@@ -20,6 +20,7 @@ import org.apache.nifi.registry.security.authorization.exception.AccessDeniedExc
 import org.apache.nifi.registry.security.authorization.resource.Authorizable
 import org.apache.nifi.registry.security.authorization.resource.ResourceType
 import org.apache.nifi.registry.service.AuthorizationService
+import org.apache.nifi.registry.service.RegistryService
 import org.apache.nifi.registry.web.security.authorization.HttpMethodAuthorizationRules
 import org.apache.nifi.registry.web.security.authorization.ResourceAuthorizationFilter
 import org.apache.nifi.registry.web.security.authorization.StandardHttpMethodAuthorizationRules
@@ -34,7 +35,8 @@ import javax.servlet.http.HttpServletResponse
 
 class ResourceAuthorizationFilterSpec extends Specification {
 
-    AuthorizableLookup authorizableLookup = new StandardAuthorizableLookup()
+    RegistryService registryService = Mock(RegistryService)
+    AuthorizableLookup authorizableLookup = new StandardAuthorizableLookup(registryService)
     AuthorizationService mockAuthorizationService = Mock(AuthorizationService)
     FilterChain mockFilterChain = Mock(FilterChain)
     ResourceAuthorizationFilter.Builder resourceAuthorizationFilterBuilder


[nifi-registry] 06/43: NIFIREG-320 - Added jetty header filters to set security headers. Setting security headers for the registry-api using spring security configuration. NIFIREG-320 - Fixed rest-api docs loading. Headers confirmed to be applied for docs. NIFIREG-320 - Removed unnecessary dependency.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 32c134130bfbaa79afc105fa2175ccd27f7320ef
Author: thenatog <th...@gmail.com>
AuthorDate: Mon Sep 23 13:16:57 2019 -0400

    NIFIREG-320 - Added jetty header filters to set security headers. Setting security headers for the registry-api using spring security configuration.
    NIFIREG-320 - Fixed rest-api docs loading. Headers confirmed to be applied for docs.
    NIFIREG-320 - Removed unnecessary dependency.
    
    This closes #231.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 .../apache/nifi/registry/jetty/JettyServer.java    | 132 ++++++++++++++-------
 .../jetty/headers/ContentSecurityPolicyFilter.java |  58 +++++++++
 .../headers/StrictTransportSecurityFilter.java     |  58 +++++++++
 .../jetty/headers/XFrameOptionsFilter.java         |  58 +++++++++
 .../jetty/headers/XSSProtectionFilter.java         |  59 +++++++++
 .../properties/NiFiRegistryProperties.java         |   4 +
 .../web/security/NiFiRegistrySecurityConfig.java   |   6 +
 7 files changed, 331 insertions(+), 44 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java
index 45619f7..387857f 100644
--- a/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java
+++ b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/JettyServer.java
@@ -17,6 +17,10 @@
 package org.apache.nifi.registry.jetty;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.jetty.headers.ContentSecurityPolicyFilter;
+import org.apache.nifi.registry.jetty.headers.StrictTransportSecurityFilter;
+import org.apache.nifi.registry.jetty.headers.XFrameOptionsFilter;
+import org.apache.nifi.registry.jetty.headers.XSSProtectionFilter;
 import org.apache.nifi.registry.properties.NiFiRegistryProperties;
 import org.apache.nifi.registry.security.crypto.CryptoKeyProvider;
 import org.eclipse.jetty.annotations.AnnotationConfiguration;
@@ -28,11 +32,10 @@ import org.eclipse.jetty.server.SecureRequestCustomizer;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.ServerConnector;
 import org.eclipse.jetty.server.SslConnectionFactory;
-import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.server.handler.ResourceHandler;
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.util.resource.ResourceCollection;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletHolder;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
 import org.eclipse.jetty.webapp.Configuration;
@@ -42,6 +45,8 @@ import org.eclipse.jetty.webapp.WebAppContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.IOException;
@@ -55,6 +60,7 @@ import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.LinkedList;
@@ -106,6 +112,37 @@ public class JettyServer {
         }
     }
 
+    /**
+     * Returns a File object for the directory containing NIFI documentation.
+     * <p>
+     * Formerly, if the docsDirectory did not exist NIFI would fail to start
+     * with an IllegalStateException and a rather unhelpful log message.
+     * NIFI-2184 updates the process such that if the docsDirectory does not
+     * exist an attempt will be made to create the directory. If that is
+     * successful NIFI will no longer fail and will start successfully barring
+     * any other errors. The side effect of the docsDirectory not being present
+     * is that the documentation links under the 'General' portion of the help
+     * page will not be accessible, but at least the process will be running.
+     *
+     * @param docsDirectory Name of documentation directory in installation directory.
+     * @return A File object to the documentation directory; else startUpFailure called.
+     */
+    private File getDocsDir(final String docsDirectory) {
+        File docsDir;
+        try {
+            docsDir = Paths.get(docsDirectory).toRealPath().toFile();
+        } catch (IOException ex) {
+            logger.info("Directory '" + docsDirectory + "' is missing. Some documentation will be unavailable.");
+            docsDir = new File(docsDirectory).getAbsoluteFile();
+            final boolean made = docsDir.mkdirs();
+            if (!made) {
+                logger.error("Failed to create 'docs' directory!");
+                startUpFailure(new IOException(docsDir.getAbsolutePath() + " could not be created"));
+            }
+        }
+        return docsDir;
+    }
+
     private void configureConnectors() {
         // create the http configuration
         final HttpConfiguration httpConfiguration = new HttpConfiguration();
@@ -254,11 +291,11 @@ public class JettyServer {
 
         final String docsContextPath = "/nifi-registry-docs";
         webDocsContext = loadWar(webDocsWar, docsContextPath);
+        addDocsServlets(webDocsContext);
 
         final HandlerCollection handlers = new HandlerCollection();
         handlers.addHandler(webUiContext);
         handlers.addHandler(webApiContext);
-        handlers.addHandler(createDocsWebApp(docsContextPath));
         handlers.addHandler(webDocsContext);
         server.setHandler(handlers);
     }
@@ -301,6 +338,15 @@ public class JettyServer {
         // configure the max form size (3x the default)
         webappContext.setMaxFormContentSize(600000);
 
+        // add HTTP security headers to all responses
+        final String ALL_PATHS = "/*";
+        ArrayList<Class<? extends Filter>> filters = new ArrayList<>(Arrays.asList(XFrameOptionsFilter.class, ContentSecurityPolicyFilter.class, XSSProtectionFilter.class));
+        if(properties.isHTTPSConfigured()) {
+            filters.add(StrictTransportSecurityFilter.class);
+        }
+
+        filters.forEach( (filter) -> addFilters(filter, ALL_PATHS, webappContext));
+
         // start out assuming the system ClassLoader will be the parent, but if additional resources were specified then
         // inject a new ClassLoader in between the system and webapp ClassLoaders that contains the additional resources
         ClassLoader parentClassLoader = ClassLoader.getSystemClassLoader();
@@ -315,6 +361,12 @@ public class JettyServer {
         return webappContext;
     }
 
+    private void addFilters(Class<? extends Filter> clazz, String path, WebAppContext webappContext) {
+        FilterHolder holder = new FilterHolder(clazz);
+        holder.setName(clazz.getSimpleName());
+        webappContext.addFilter(holder, path, EnumSet.allOf(DispatcherType.class));
+    }
+
     private URL[] getWebApiAdditionalClasspath() {
         final String dbDriverDir = properties.getDatabaseDriverDirectory();
 
@@ -370,51 +422,43 @@ public class JettyServer {
         return resources.toArray(new URL[resources.size()]);
     }
 
-    private ContextHandler createDocsWebApp(final String contextPath) throws IOException {
-        final ResourceHandler resourceHandler = new ResourceHandler();
-        resourceHandler.setDirectoriesListed(false);
-
-        // load the docs directory
-        String docsDirectory = docsLocation;
-        if (StringUtils.isBlank(docsDirectory)) {
-            docsDirectory = "docs";
-        }
-
-        File docsDir;
+    private void addDocsServlets(WebAppContext docsContext) {
         try {
-            docsDir = Paths.get(docsDirectory).toRealPath().toFile();
-        } catch (IOException ex) {
-            logger.warn("Directory '" + docsDirectory + "' is missing. Some documentation will be unavailable.");
-            docsDir = new File(docsDirectory).getAbsoluteFile();
-            final boolean made = docsDir.mkdirs();
-            if (!made) {
-                logger.error("Failed to create 'docs' directory!");
-                startUpFailure(new IOException(docsDir.getAbsolutePath() + " could not be created"));
+            // Load the nifi-registry/docs directory
+            final File docsDir = getDocsDir(docsLocation);
+
+            // Create the servlet which will serve the static resources
+            ServletHolder defaultHolder = new ServletHolder("default", DefaultServlet.class);
+            defaultHolder.setInitParameter("dirAllowed", "false");
+
+            ServletHolder docs = new ServletHolder("docs", DefaultServlet.class);
+            docs.setInitParameter("resourceBase", docsDir.getPath());
+            docs.setInitParameter("dirAllowed", "false");
+
+            docsContext.addServlet(docs, "/html/*");
+            docsContext.addServlet(defaultHolder, "/");
+
+            // load the rest documentation
+            final File webApiDocsDir = new File(webApiContext.getTempDirectory(), "webapp/docs");
+            if (!webApiDocsDir.exists()) {
+                final boolean made = webApiDocsDir.mkdirs();
+                if (!made) {
+                    throw new RuntimeException(webApiDocsDir.getAbsolutePath() + " could not be created");
+                }
             }
-        }
 
-        final Resource docsResource = Resource.newResource(docsDir);
+            ServletHolder apiDocs = new ServletHolder("apiDocs", DefaultServlet.class);
+            apiDocs.setInitParameter("resourceBase", webApiDocsDir.getPath());
+            apiDocs.setInitParameter("dirAllowed", "false");
 
-        // load the rest documentation
-        final File webApiDocsDir = new File(webApiContext.getTempDirectory(), "webapp/docs");
-        if (!webApiDocsDir.exists()) {
-            final boolean made = webApiDocsDir.mkdirs();
-            if (!made) {
-                throw new RuntimeException(webApiDocsDir.getAbsolutePath() + " could not be created");
-            }
-        }
-        final Resource webApiDocsResource = Resource.newResource(webApiDocsDir);
-
-        // create resources for both docs locations
-        final ResourceCollection resources = new ResourceCollection(docsResource, webApiDocsResource);
-        resourceHandler.setBaseResource(resources);
+            docsContext.addServlet(apiDocs, "/rest-api/*");
 
-        // create the context handler
-        final ContextHandler handler = new ContextHandler(contextPath);
-        handler.setHandler(resourceHandler);
+            logger.info("Loading documents web app with context path set to " + docsContext.getContextPath());
 
-        logger.info("Loading documents web app with context path set to " + contextPath);
-        return handler;
+        } catch (Exception ex) {
+            logger.error("Unhandled Exception in createDocsWebApp: " + ex.getMessage());
+            startUpFailure(ex);
+        }
     }
 
     public void start() {
diff --git a/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/ContentSecurityPolicyFilter.java b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/ContentSecurityPolicyFilter.java
new file mode 100644
index 0000000..758e939
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/ContentSecurityPolicyFilter.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.jetty.headers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * A filter to apply the Content Security Policy header.
+ *
+ */
+public class ContentSecurityPolicyFilter implements Filter {
+    private static final String HEADER = "Content-Security-Policy";
+    private static final String POLICY = "frame-ancestors 'self'";
+
+    private static final Logger logger = LoggerFactory.getLogger(ContentSecurityPolicyFilter.class);
+
+    @Override
+    public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain filterChain)
+            throws IOException, ServletException {
+
+        final HttpServletResponse response = (HttpServletResponse) resp;
+        response.setHeader(HEADER, POLICY);
+
+        filterChain.doFilter(req, resp);
+    }
+
+    @Override
+    public void init(final FilterConfig config) {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/StrictTransportSecurityFilter.java b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/StrictTransportSecurityFilter.java
new file mode 100644
index 0000000..7f0f913
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/StrictTransportSecurityFilter.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.jetty.headers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * A filter to apply the HTTP Strict Transport Security (HSTS) HTTP header. This forces the browser to use HTTPS for
+ * all
+ */
+public class StrictTransportSecurityFilter implements Filter {
+    private static final String HEADER = "Strict-Transport-Security";
+    private static final String POLICY = "max-age=31540000";
+
+    private static final Logger logger = LoggerFactory.getLogger(StrictTransportSecurityFilter.class);
+
+    @Override
+    public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain filterChain)
+            throws IOException, ServletException {
+
+        final HttpServletResponse response = (HttpServletResponse) resp;
+        response.setHeader(HEADER, POLICY);
+
+        filterChain.doFilter(req, resp);
+    }
+
+    @Override
+    public void init(final FilterConfig config) {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/XFrameOptionsFilter.java b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/XFrameOptionsFilter.java
new file mode 100644
index 0000000..fad5bbc
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/XFrameOptionsFilter.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.jetty.headers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * A filter to apply the X-Frame-Options header.
+ *
+ */
+public class XFrameOptionsFilter implements Filter {
+    private static final String HEADER = "X-Frame-Options";
+    private static final String POLICY = "SAMEORIGIN";
+
+    private static final Logger logger = LoggerFactory.getLogger(XFrameOptionsFilter.class);
+
+    @Override
+    public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain filterChain)
+            throws IOException, ServletException {
+
+        final HttpServletResponse response = (HttpServletResponse) resp;
+        response.setHeader(HEADER, POLICY);
+
+        filterChain.doFilter(req, resp);
+    }
+
+    @Override
+    public void init(final FilterConfig config) {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/XSSProtectionFilter.java b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/XSSProtectionFilter.java
new file mode 100644
index 0000000..62792f1
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-jetty/src/main/java/org/apache/nifi/registry/jetty/headers/XSSProtectionFilter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.jetty.headers;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * A filter to apply the Cross Site Scripting (XSS) HTTP header. Protects against reflected cross-site scripting attacks.
+ * The browser will prevent rendering of the page if an attack is detected.
+ */
+
+public class XSSProtectionFilter implements Filter {
+    private static final String HEADER = "X-XSS-Protection";
+    private static final String POLICY = "1; mode=block";
+
+    private static final Logger logger = LoggerFactory.getLogger(XSSProtectionFilter.class);
+
+    @Override
+    public void doFilter(final ServletRequest req, final ServletResponse resp, final FilterChain filterChain)
+            throws IOException, ServletException {
+
+        final HttpServletResponse response = (HttpServletResponse) resp;
+        response.setHeader(HEADER, POLICY);
+
+        filterChain.doFilter(req, resp);
+    }
+
+    @Override
+    public void init(final FilterConfig config) {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
index 31133eb..e1e9a39 100644
--- a/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
+++ b/nifi-registry-core/nifi-registry-properties/src/main/java/org/apache/nifi/registry/properties/NiFiRegistryProperties.java
@@ -118,6 +118,10 @@ public class NiFiRegistryProperties extends Properties {
         return getPropertyAsInteger(WEB_HTTPS_PORT);
     }
 
+    public boolean isHTTPSConfigured() {
+        return getSslPort() != null;
+    }
+
     public String getHttpsHost() {
         return getProperty(WEB_HTTPS_HOST);
     }
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java
index 20a6e0d..b792830 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/NiFiRegistrySecurityConfig.java
@@ -100,6 +100,12 @@ public class NiFiRegistrySecurityConfig extends WebSecurityConfigurerAdapter {
                 .sessionManagement()
                     .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
 
+        // Apply security headers for registry API. Security headers for docs and UI are applied with Jetty filters in registry-core.
+        http.headers().xssProtection();
+        http.headers().contentSecurityPolicy("frame-ancestors 'self'");
+        http.headers().httpStrictTransportSecurity().maxAgeInSeconds(31540000);
+        http.headers().frameOptions().sameOrigin();
+
         // x509
         http.addFilterBefore(x509AuthenticationFilter(), AnonymousAuthenticationFilter.class);
 


[nifi-registry] 16/43: NIFIREG-334 Changes to support Java 11 - Upgrade Groovy to 2.5.x - Setup jigsaw profile to optionally include Java 11 dependencies - Modify assembly to create lib/java11 dir - Modify RunNiFiRegistry to optionally add lib/java11 to the classpath - Modify OSUtils to correctly handle PIDs when running on Java 11 - Update assembly LICENSE to include Jakarta artifacts under EDL - Updating Travis config to include a Java 11 build

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit a503ba153b9e6259e9c57c532f03dc26f84730ac
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Tue Oct 15 14:44:50 2019 -0400

    NIFIREG-334 Changes to support Java 11
    - Upgrade Groovy to 2.5.x
    - Setup jigsaw profile to optionally include Java 11 dependencies
    - Modify assembly to create lib/java11 dir
    - Modify RunNiFiRegistry to optionally add lib/java11 to the classpath
    - Modify OSUtils to correctly handle PIDs when running on Java 11
    - Update assembly LICENSE to include Jakarta artifacts under EDL
    - Updating Travis config to include a Java 11 build
    
    This closes #241.
---
 .travis.yml                                        |  56 ++++-
 nifi-registry-assembly/LICENSE                     | 266 +++++++++++++++++++++
 nifi-registry-assembly/pom.xml                     |  10 +
 .../src/main/assembly/dependencies.xml             |  20 ++
 .../nifi/registry/bootstrap/RunNiFiRegistry.java   |  22 ++
 .../nifi/registry/bootstrap/util/OSUtils.java      |  41 +++-
 .../nifi-registry-bundle-utils/pom.xml             |  16 ++
 .../nifi-registry-data-model/pom.xml               |  16 ++
 nifi-registry-core/nifi-registry-framework/pom.xml |  44 ++--
 .../nifi-registry-properties/pom.xml               |   3 +-
 .../AESSensitivePropertyProviderTest.groovy        |   3 +-
 .../nifi-registry-security-utils/pom.xml           |   6 +-
 nifi-registry-core/nifi-registry-web-api/pom.xml   |  31 ++-
 nifi-registry-core/pom.xml                         |   2 +-
 pom.xml                                            |  84 ++++++-
 15 files changed, 569 insertions(+), 51 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index e83abde..ac28080 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,15 +15,52 @@
 
 language: java
 
-env:
-    - USER_LANGUAGE=en USER_REGION=US'
-    - USER_LANGUAGE=fr USER_REGION=FR'
-    - USER_LANGUAGE=ja USER_REGION=JP'
+matrix:
+  include:
+    - stage: "Build"
+      name: "Build Java 8 EN"
+      jdk: openjdk8
+      script: >-
+        mvn clean install -Pcontrib-check,jsUnitTests
+        -Dmaven.surefire.arguments="-Duser.language=en -Duser.region=US"
+        | grep -v -F -f .travis-output-filters
+        && exit ${PIPESTATUS[0]}
+    - stage: "Build"
+      name: "Build Java 8 FR"
+      jdk: openjdk8
+      script: >-
+        mvn clean install -Pcontrib-check,jsUnitTests
+        -Dmaven.surefire.arguments="-Duser.language=fr -Duser.region=FR"
+        | grep -v -F -f .travis-output-filters
+        && exit ${PIPESTATUS[0]}
+    - stage: "Build"
+      name: "Build Java 8 JP"
+      jdk: openjdk8
+      script: >-
+        mvn clean install -Pcontrib-check,jsUnitTests
+        -Dmaven.surefire.arguments="-Duser.language=ja -Duser.region=JP"
+        | grep -v -F -f .travis-output-filters
+        && exit ${PIPESTATUS[0]}
+    - stage: "Build"
+      name: "Build Java 11 EN"
+      # Do not specify "jdk:" here, install-jdk.sh will download the JDK set JAVA_HOME appropriately
+      before_script:
+        # Download the newest version of sormuras' install-jdk.sh to /tmp
+        # install-jdk.sh is used by Travis internally, sormoras is the maintainer of that script
+        - wget -O /tmp/install-jdk.sh https://github.com/sormuras/bach/raw/master/install-jdk.sh
+        # Need to specifically install AdoptOpenJDK 11.0.4 (Linux, HotSpot) since Travis does not offer it by default
+        # The link to the AdoptOpenJDK 11.0.4 .tar.gz is taken directly from AdoptOpenJDK's website
+        - >-
+          source /tmp/install-jdk.sh
+          --url 'https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.4%2B11/OpenJDK11U-jdk_x64_linux_hotspot_11.0.4_11.tar.gz'
+      script: >-
+        mvn clean install -Pcontrib-check,jsUnitTests
+        -Dmaven.surefire.arguments="-Duser.language=en -Duser.region=US"
+        | grep -v -F -f .travis-output-filters
+        && exit ${PIPESTATUS[0]}
 
-os: linux
-
-jdk:
-    - openjdk8
+os:
+    - linux
 
 # Caches mvn repository in order to speed up builds
 cache:
@@ -55,7 +92,4 @@ before_script:
 # skip the installation step entirely
 install: true
 
-#build commands
-script:
-    - mvn clean install -Pcontrib-check,jsUnitTests | grep -v -F -f .travis-output-filters && exit ${PIPESTATUS[0]}
 
diff --git a/nifi-registry-assembly/LICENSE b/nifi-registry-assembly/LICENSE
index 871a4a0..68891c9 100644
--- a/nifi-registry-assembly/LICENSE
+++ b/nifi-registry-assembly/LICENSE
@@ -1346,3 +1346,269 @@ For details see https://www.eclipse.org/org/documents/edl-v10.php
     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta jaxb-api' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta jaxb-ri' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta jaxb-fi' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta jaxb-istack-commons' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta jaxb-stax-ex' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta txw2 runtime' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+This product bundles 'Jakarta Activation' which is available under a Eclipse Distribution License - v 1.0 license.
+For details see https://www.eclipse.org/org/documents/edl-v10.php
+
+    Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors.
+
+    All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, are permitted provided that the following
+    conditions are met:
+
+    - Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    - Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    - Neither the name of the Eclipse Foundation, Inc. nor the
+      names of its contributors may be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+    CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+    INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+    ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/nifi-registry-assembly/pom.xml b/nifi-registry-assembly/pom.xml
index 319bcd2..135434c 100644
--- a/nifi-registry-assembly/pom.xml
+++ b/nifi-registry-assembly/pom.xml
@@ -131,6 +131,16 @@
             <scope>runtime</scope>
             <type>zip</type>
         </dependency>
+        <!-- Dependencies required for running on Java 11 that will be placed in the lib/java11 dir -->
+        <!-- TODO: remove these once minimum Java version is 11 and these can be bundle directly into the application -->
+        <dependency>
+            <groupId>jakarta.xml.bind</groupId>
+            <artifactId>jakarta.xml.bind-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jaxb</groupId>
+            <artifactId>jaxb-runtime</artifactId>
+        </dependency>
     </dependencies>
 
     <properties>
diff --git a/nifi-registry-assembly/src/main/assembly/dependencies.xml b/nifi-registry-assembly/src/main/assembly/dependencies.xml
index d7985ac..da25c39 100644
--- a/nifi-registry-assembly/src/main/assembly/dependencies.xml
+++ b/nifi-registry-assembly/src/main/assembly/dependencies.xml
@@ -53,6 +53,21 @@
             </includes>
         </dependencySet>
 
+        <!-- Write out the libs for java11 to its own dir -->
+        <!-- TODO: remove these once minimum Java version is 11 and these can be bundle directly into the application -->
+        <dependencySet>
+            <scope>runtime</scope>
+            <useProjectArtifact>false</useProjectArtifact>
+            <outputDirectory>lib/java11</outputDirectory>
+            <directoryMode>0770</directoryMode>
+            <fileMode>0664</fileMode>
+            <useTransitiveFiltering>true</useTransitiveFiltering>
+            <includes>
+                <include>jakarta.xml.bind:jakarta.xml.bind-api</include>
+                <include>org.glassfish.jaxb:jaxb-runtime</include>
+            </includes>
+        </dependencySet>
+
         <!-- Write out all dependency artifacts to lib directory -->
         <dependencySet>
             <scope>runtime</scope>
@@ -68,6 +83,11 @@
                 <exclude>nifi-registry-docs</exclude>
                 <exclude>nifi-registry-ranger-assembly</exclude>
                 <exclude>nifi-registry-aws-assembly</exclude>
+
+                <!-- Exclude any jaxb dependencies because they will be in lib/java11 -->
+                <!-- TODO: remove these once minimum Java version is 11 and these can be bundle directly into the application -->
+                <exclude>jakarta.xml.bind:jakarta.xml.bind-api</exclude>
+                <exclude>org.glassfish.jaxb:jaxb-runtime</exclude>
             </excludes>
         </dependencySet>
         
diff --git a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
index af11fa4..b73dcfc 100644
--- a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
+++ b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
@@ -48,6 +48,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
@@ -920,6 +921,20 @@ public class RunNiFiRegistry {
             cpFiles.add(file.getAbsolutePath());
         }
 
+        final String runtimeJavaVersion = System.getProperty("java.version");
+        defaultLogger.info("Runtime Java version: {}", runtimeJavaVersion);
+        if (Integer.parseInt(runtimeJavaVersion.substring(0, runtimeJavaVersion.indexOf('.'))) >= 11) {
+            // If running on Java 11 or greater, add lib/java11 to the classpath.
+            // TODO: Once the minimum Java version requirement of NiFi Registry is 11, this processing should be removed.
+            final String libJava11Filename = replaceNull(props.get("lib.dir"), "./lib").trim() + "/java11";
+            final File libJava11Dir = getFile(libJava11Filename, workingDir);
+            if (libJava11Dir.exists()) {
+                for (final File file : Objects.requireNonNull(libJava11Dir.listFiles((dir, filename) -> filename.toLowerCase().endsWith(".jar")))) {
+                    cpFiles.add(file.getAbsolutePath());
+                }
+            }
+        }
+
         final StringBuilder classPathBuilder = new StringBuilder();
         for (int i = 0; i < cpFiles.size(); i++) {
             final String filename = cpFiles.get(i);
@@ -961,6 +976,13 @@ public class RunNiFiRegistry {
         cmd.add("-Dnifi.registry.bootstrap.config.docs.dir=" + nifiRegistryDocsDir);
         cmd.add("-Dapp=NiFiRegistry");
         cmd.add("-Dorg.apache.nifi.registry.bootstrap.config.log.dir=" + nifiRegistryLogDir);
+
+        if (runtimeJavaVersion.startsWith("9") || runtimeJavaVersion.startsWith("10")) {
+            // running on Java 9+, java.xml.bind module must be made available
+            // running on Java 9 or 10, internal module java.xml.bind module must be made available
+            cmd.add("--add-modules=java.xml.bind");
+        }
+
         cmd.add("org.apache.nifi.registry.NiFiRegistry");
 
         builder.command(cmd);
diff --git a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/util/OSUtils.java b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/util/OSUtils.java
index 17c43df..4b70866 100644
--- a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/util/OSUtils.java
+++ b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/util/OSUtils.java
@@ -17,12 +17,14 @@
 
 package org.apache.nifi.registry.bootstrap.util;
 
-import java.lang.reflect.Field;
-
-import org.slf4j.Logger;
 import com.sun.jna.Pointer;
 import com.sun.jna.platform.win32.Kernel32;
 import com.sun.jna.platform.win32.WinNT;
+import org.slf4j.Logger;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 
 /**
  * OS specific utilities with generic method interfaces
@@ -94,14 +96,39 @@ public final class OSUtils {
      * Purpose for the Logger is to log any interaction for debugging.
      */
     public static Long getProcessId(final Process process, final Logger logger) {
-        if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
-            return getUnicesPid(process, logger);
+        /*
+         * NiFi Registry built with Java 1.8 and running on Java 9.  Reflectively invoke Process.pid() on the given process
+         * instance to get the PID of this Java process.  Reflection is required in this scenario due to NiFi Registry being
+         * compiled on Java 1.8, which does not have the Process API improvements available in Java 9.
+         *
+         * Otherwise, if NiFi is running on Java 1.8, attempt to get PID using capabilities available on Java 1.8.
+         *
+         * TODO: When minimum Java version updated to Java 9+, this class should be removed with the addition
+         *  of the pid method to the Process API.
+         */
+        Long pid = null;
+        if (!System.getProperty("java.version").startsWith("1.")) {
+            try {
+                Method pidMethod = process.getClass().getMethod("pid");
+                pidMethod.setAccessible(true);
+                Object pidMethodResult = pidMethod.invoke(process);
+                if (Long.class.isAssignableFrom(pidMethodResult.getClass())) {
+                    pid = (Long) pidMethodResult;
+                } else {
+                    logger.debug("Could not determine PID for child process because returned PID was not " +
+                            "assignable to type " + Long.class.getName());
+                }
+            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+                logger.debug("Could not find PID for child process due to {}", e);
+            }
+        } else if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
+            pid = getUnicesPid(process, logger);
         } else if (process.getClass().getName().equals("java.lang.Win32Process")
                 || process.getClass().getName().equals("java.lang.ProcessImpl")) {
-            return getWindowsProcessId(process, logger);
+            pid = getWindowsProcessId(process, logger);
         }
 
-        return null;
+        return pid;
     }
 
 }
diff --git a/nifi-registry-core/nifi-registry-bundle-utils/pom.xml b/nifi-registry-core/nifi-registry-bundle-utils/pom.xml
index 14e0f1c..ef2ab07 100644
--- a/nifi-registry-core/nifi-registry-bundle-utils/pom.xml
+++ b/nifi-registry-core/nifi-registry-bundle-utils/pom.xml
@@ -33,4 +33,20 @@
         </dependency>
     </dependencies>
 
+    <profiles>
+        <profile>
+            <!-- This profile provides configuration to allow NiFi Registry to be compiled on JDKs above 1.8. -->
+            <id>jigsaw</id>
+            <activation>
+                <jdk>(1.8,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>jakarta.xml.bind</groupId>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
 </project>
diff --git a/nifi-registry-core/nifi-registry-data-model/pom.xml b/nifi-registry-core/nifi-registry-data-model/pom.xml
index 180a5c2..8348ef3 100644
--- a/nifi-registry-core/nifi-registry-data-model/pom.xml
+++ b/nifi-registry-core/nifi-registry-data-model/pom.xml
@@ -34,4 +34,20 @@
             <artifactId>javax.ws.rs-api</artifactId>
         </dependency>
     </dependencies>
+
+    <profiles>
+        <profile>
+            <!-- This profile provides configuration to allow NiFi Registry to be compiled on JDKs above 1.8. -->
+            <id>jigsaw</id>
+            <activation>
+                <jdk>(1.8,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>jakarta.xml.bind</groupId>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
 </project>
diff --git a/nifi-registry-core/nifi-registry-framework/pom.xml b/nifi-registry-core/nifi-registry-framework/pom.xml
index 8d7f2c1..da26284 100644
--- a/nifi-registry-core/nifi-registry-framework/pom.xml
+++ b/nifi-registry-core/nifi-registry-framework/pom.xml
@@ -138,15 +138,6 @@
                 </executions>
             </plugin>
             <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.6.1</version>
-                <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
-                </configuration>
-            </plugin>
-            <plugin>
                 <groupId>org.apache.rat</groupId>
                 <artifactId>apache-rat-plugin</artifactId>
                 <configuration>
@@ -279,6 +270,11 @@
                     <groupId>org.hibernate</groupId>
                     <artifactId>hibernate-core</artifactId>
                 </exclusion>
+                <!-- JDK 8 will already have jaxb-api, and JDKs above 8 we activate a profile to include it -->
+                <exclusion>
+                    <groupId>javax.xml.bind</groupId>
+                    <artifactId>jaxb-api</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
         <dependency>
@@ -370,13 +366,11 @@
         <dependency>
             <groupId>org.spockframework</groupId>
             <artifactId>spock-core</artifactId>
-            <version>1.0-groovy-2.4</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
-            <artifactId>groovy-all</artifactId>
-            <version>2.4.12</version>
+            <artifactId>groovy-test</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
@@ -390,11 +384,31 @@
             <artifactId>apacheds-all</artifactId>
             <version>2.0.0-M24</version>
             <scope>test</scope>
-	</dependency>
-	<dependency>
+	    </dependency>
+	    <dependency>
             <groupId>org.apache.nifi.registry</groupId>
             <artifactId>nifi-registry-flow-diff</artifactId>
             <version>0.6.0-SNAPSHOT</version>
         </dependency>
-    </dependencies>
+        </dependencies>
+
+    <profiles>
+        <profile>
+            <!-- This profile provides configuration to allow NiFi Registry to be compiled on JDKs above 1.8. -->
+            <id>jigsaw</id>
+            <activation>
+                <jdk>(1.8,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>jakarta.xml.bind</groupId>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jaxb</groupId>
+                    <artifactId>jaxb-runtime</artifactId>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
 </project>
diff --git a/nifi-registry-core/nifi-registry-properties/pom.xml b/nifi-registry-core/nifi-registry-properties/pom.xml
index e8fddd8..1c3a95c 100644
--- a/nifi-registry-core/nifi-registry-properties/pom.xml
+++ b/nifi-registry-core/nifi-registry-properties/pom.xml
@@ -53,8 +53,7 @@
         </dependency>
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
-            <artifactId>groovy-all</artifactId>
-            <version>2.4.12</version>
+            <artifactId>groovy-test</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/nifi-registry-core/nifi-registry-properties/src/test/groovy/org/apache/nifi/registry/properties/AESSensitivePropertyProviderTest.groovy b/nifi-registry-core/nifi-registry-properties/src/test/groovy/org/apache/nifi/registry/properties/AESSensitivePropertyProviderTest.groovy
index ed071ac..bad659f 100644
--- a/nifi-registry-core/nifi-registry-properties/src/test/groovy/org/apache/nifi/registry/properties/AESSensitivePropertyProviderTest.groovy
+++ b/nifi-registry-core/nifi-registry-properties/src/test/groovy/org/apache/nifi/registry/properties/AESSensitivePropertyProviderTest.groovy
@@ -17,7 +17,6 @@
 package org.apache.nifi.registry.properties
 
 import org.bouncycastle.jce.provider.BouncyCastleProvider
-import org.bouncycastle.util.encoders.DecoderException
 import org.bouncycastle.util.encoders.Hex
 import org.junit.*
 import org.junit.runner.RunWith
@@ -83,7 +82,7 @@ class AESSensitivePropertyProviderTest extends GroovyTestCase {
                 if (Cipher.getMaxAllowedKeyLength("AES") < keySize) {
                     throw new IllegalArgumentException("The JCE unlimited strength cryptographic jurisdiction policies are not installed, so the max key size is 128 bits")
                 }
-                return KEY_256_HEX[0..<(keySize / 4)]
+                return KEY_256_HEX[0..<keySize.intdiv(4)]
             default:
                 throw new IllegalArgumentException("Key size ${keySize} bits is not valid")
         }
diff --git a/nifi-registry-core/nifi-registry-security-utils/pom.xml b/nifi-registry-core/nifi-registry-security-utils/pom.xml
index 94ac9a0..dbb46e2 100644
--- a/nifi-registry-core/nifi-registry-security-utils/pom.xml
+++ b/nifi-registry-core/nifi-registry-security-utils/pom.xml
@@ -40,7 +40,11 @@
         <dependency>
             <groupId>org.spockframework</groupId>
             <artifactId>spock-core</artifactId>
-            <version>1.0-groovy-2.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-test</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
diff --git a/nifi-registry-core/nifi-registry-web-api/pom.xml b/nifi-registry-core/nifi-registry-web-api/pom.xml
index 42cfaa8..3d7e371 100644
--- a/nifi-registry-core/nifi-registry-web-api/pom.xml
+++ b/nifi-registry-core/nifi-registry-web-api/pom.xml
@@ -282,6 +282,28 @@
                 </plugins>
             </build>
         </profile>
+        <profile>
+            <!-- This profile provides configuration to allow NiFi Registry to be compiled on JDKs above 1.8. -->
+            <id>jigsaw</id>
+            <activation>
+                <jdk>(1.8,)</jdk>
+            </activation>
+            <!-- These dependencies would normally be transitive deps of framework and data model, but we want to
+                redeclare them with provided scope so that they don't end up in WEB-INF/lib of the WAR, they will
+                be added to the lib/java11 directory and added to the classpath based on the JVM being used -->
+            <dependencies>
+                <dependency>
+                    <groupId>jakarta.xml.bind</groupId>
+                    <artifactId>jakarta.xml.bind-api</artifactId>
+                    <scope>provided</scope>
+                </dependency>
+                <dependency>
+                    <groupId>org.glassfish.jaxb</groupId>
+                    <artifactId>jaxb-runtime</artifactId>
+                    <scope>provided</scope>
+                </dependency>
+            </dependencies>
+        </profile>
     </profiles>
 
     <dependencies>
@@ -300,6 +322,11 @@
                     <groupId>org.springframework</groupId>
                     <artifactId>spring-aop</artifactId>
                 </exclusion>
+                <!-- JDK 8 will already have jaxb-api, and JDKs above 8 we activate a profile to include it -->
+                <exclusion>
+                    <groupId>javax.xml.bind</groupId>
+                    <artifactId>jaxb-api</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
         <!-- Exclude micrometer-core because it creates a class cast issue with logback, revisit later -->
@@ -424,13 +451,11 @@
         <dependency>
             <groupId>org.spockframework</groupId>
             <artifactId>spock-core</artifactId>
-            <version>1.0-groovy-2.4</version>
             <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>org.codehaus.groovy</groupId>
-            <artifactId>groovy-all</artifactId>
-            <version>2.4.12</version>
+            <artifactId>groovy-test</artifactId>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/nifi-registry-core/pom.xml b/nifi-registry-core/pom.xml
index 559eac6..ac18996 100644
--- a/nifi-registry-core/pom.xml
+++ b/nifi-registry-core/pom.xml
@@ -47,7 +47,7 @@
         <module>nifi-registry-docker</module>
         <module>nifi-registry-bundle-utils</module>
         <module>nifi-registry-test</module>
-	<module>nifi-registry-revision</module>
+	    <module>nifi-registry-revision</module>
     </modules>
 
     <dependencyManagement>
diff --git a/pom.xml b/pom.xml
index cfa73af..ae1bb35 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,6 +103,9 @@
         <swagger.ui.version>3.12.0</swagger.ui.version>
         <testcontainers.version>1.11.2</testcontainers.version>
 	    <h2.version>1.4.197</h2.version>
+        <groovy.version>2.5.4</groovy.version>
+        <groovy.eclipse.compiler.version>3.4.0-01</groovy.eclipse.compiler.version>
+        <jaxb.version>2.3.2</jaxb.version>
     </properties>
 
     <repositories>
@@ -151,9 +154,19 @@
                 <enabled>false</enabled>
             </snapshots>
         </pluginRepository>
+        <pluginRepository>
+            <id>bintray</id>
+            <name>Groovy Bintray</name>
+            <url>https://dl.bintray.com/groovy/maven</url>
+            <releases>
+                <updatePolicy>never</updatePolicy>
+            </releases>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+        </pluginRepository>
     </pluginRepositories>
 
-
     <dependencyManagement>
         <dependencies>
             <!-- Logging dependencies that will be directly in lib -->
@@ -199,6 +212,17 @@
                 <artifactId>commons-lang3</artifactId>
                 <version>3.5</version>
             </dependency>
+        <!-- lib/java11 -->
+            <dependency>
+                <groupId>jakarta.xml.bind</groupId>
+                <artifactId>jakarta.xml.bind-api</artifactId>
+                <version>${jaxb.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jaxb</groupId>
+                <artifactId>jaxb-runtime</artifactId>
+                <version>${jaxb.version}</version>
+            </dependency>
 	    <!-- NiFi Registry Modules -->
             <dependency>
                 <groupId>org.apache.nifi.registry</groupId>
@@ -249,7 +273,38 @@
             <dependency>
                 <groupId>org.mockito</groupId>
                 <artifactId>mockito-core</artifactId>
-                <version>2.7.22</version>
+                <version>2.28.2</version>
+                <scope>test</scope>
+            </dependency>
+            <!-- force mockito-core to a newer version -->
+            <dependency>
+                <groupId>net.bytebuddy</groupId>
+                <artifactId>byte-buddy</artifactId>
+                <version>1.9.10</version>
+            </dependency>
+            <!-- force mockito-core to a newer version -->
+            <dependency>
+                <groupId>net.bytebuddy</groupId>
+                <artifactId>byte-buddy-agent</artifactId>
+                <version>1.9.10</version>
+            </dependency>
+            <!-- exclude all transitive groovy deps so that spock uses whatever is directly declared -->
+            <dependency>
+                <groupId>org.spockframework</groupId>
+                <artifactId>spock-core</artifactId>
+                <version>1.3-groovy-2.5</version>
+                <scope>test</scope>
+                <exclusions>
+                    <exclusion>
+                        <groupId>org.codehaus.groovy</groupId>
+                        <artifactId>*</artifactId>
+                    </exclusion>
+                </exclusions>
+            </dependency>
+            <dependency>
+                <groupId>org.codehaus.groovy</groupId>
+                <artifactId>groovy-test</artifactId>
+                <version>${groovy.version}</version>
                 <scope>test</scope>
             </dependency>
         </dependencies>
@@ -275,7 +330,7 @@
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-compiler-plugin</artifactId>
-                    <version>3.2</version>
+                    <version>3.8.1</version>
                     <configuration>
                         <fork>true</fork>
                         <optimize>true</optimize>
@@ -286,7 +341,7 @@
                 <plugin>
                     <groupId>org.codehaus.groovy</groupId>
                     <artifactId>groovy-eclipse-compiler</artifactId>
-                    <version>2.9.2-01</version>
+                    <version>${groovy.eclipse.compiler.version}</version>
                     <extensions>true</extensions>
                 </plugin>
                 <plugin>
@@ -347,7 +402,7 @@
                 <plugin>
                     <groupId>org.codehaus.mojo</groupId>
                     <artifactId>jaxb2-maven-plugin</artifactId>
-                    <version>2.3.1</version>
+                    <version>2.5.0</version>
                 </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
@@ -450,19 +505,19 @@
                     </execution>
                 </executions>
                 <configuration>
-                    <source>1.8</source>
-                    <target>1.8</target>
+                    <source>${maven.compiler.source}</source>
+                    <target>${maven.compiler.target}</target>
                 </configuration>
                 <dependencies>
                     <dependency>
                         <groupId>org.codehaus.groovy</groupId>
                         <artifactId>groovy-eclipse-compiler</artifactId>
-                        <version>2.9.2-01</version>
+                        <version>${groovy.eclipse.compiler.version}</version>
                     </dependency>
                     <dependency>
                         <groupId>org.codehaus.groovy</groupId>
                         <artifactId>groovy-eclipse-batch</artifactId>
-                        <version>2.4.3-01</version>
+                        <version>${groovy.version}-01</version>
                     </dependency>
                 </dependencies>
             </plugin>
@@ -720,6 +775,17 @@
                 </pluginManagement>
             </build>
         </profile>
+        <profile>
+            <!-- This profile provides configuration to allow NiFi Registry to be compiled on JDKs above 1.8. -->
+            <id>jigsaw</id>
+            <activation>
+                <jdk>(1.8,)</jdk>
+            </activation>
+            <properties>
+                <maven.compiler.source>11</maven.compiler.source>
+                <maven.compiler.target>11</maven.compiler.target>
+            </properties>
+        </profile>
     </profiles>
 
 </project>


[nifi-registry] 05/43: NIFIREG-318 Change bootstrap port command handling

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit ff54171455e5ff64526e4f465de9e90352d5fac4
Author: Kevin Doran <kd...@apache.org>
AuthorDate: Wed Sep 11 17:07:29 2019 -0400

    NIFIREG-318 Change bootstrap port command handling
---
 .../org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java    | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
index c3bc172..e7a46b7 100644
--- a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
+++ b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
@@ -99,8 +99,10 @@ public class RunNiFiRegistry {
     public static final String PING_CMD = "PING";
     public static final String DUMP_CMD = "DUMP";
 
+    private static final int UNINITIALIZED_CC_PORT = -1;
+
     private volatile boolean autoRestartNiFiRegistry = true;
-    private volatile int ccPort = -1;
+    private volatile int ccPort = UNINITIALIZED_CC_PORT;
     private volatile long nifiRegistryPid = -1L;
     private volatile String secretKey;
     private volatile ShutdownHook shutdownHook;
@@ -1178,6 +1180,12 @@ public class RunNiFiRegistry {
     }
 
     void setNiFiRegistryCommandControlPort(final int port, final String secretKey) throws IOException {
+
+        if (this.secretKey != null && this.ccPort != UNINITIALIZED_CC_PORT) {
+            defaultLogger.warn("Blocking attempt to change NiFi Registry command port and secret after they have already been initialized. requestedPort={}", port);
+            return;
+        }
+
         this.ccPort = port;
         this.secretKey = secretKey;
 


[nifi-registry] 01/43: NIFIREG-314 Remove reference to HipChat from README

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit eeb8621ad6f09e20b1f3b23fd7b2cbc5e3d56624
Author: Andrew Lim <an...@gmail.com>
AuthorDate: Wed Sep 4 15:46:03 2019 -0400

    NIFIREG-314 Remove reference to HipChat from README
---
 nifi-registry-assembly/README.md | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/nifi-registry-assembly/README.md b/nifi-registry-assembly/README.md
index ea921fd..f6d1bbd 100644
--- a/nifi-registry-assembly/README.md
+++ b/nifi-registry-assembly/README.md
@@ -35,11 +35,15 @@ To start NiFi Registry:
 - Direct your browser to http://localhost:18080/nifi-registry/
 
 ## Getting Help
+
 If you have questions, you can reach out to our mailing list: dev@nifi.apache.org
-([archive](https://mail-archives.apache.org/mod_mbox/nifi-dev)).
-We're also often available in IRC: #nifi on
-[irc.freenode.net](https://webchat.freenode.net/?channels=#nifi) 
-and in #NiFi on [ASF HipChat](https://www.hipchat.com/gzh2m5YML).
+([archive](http://mail-archives.apache.org/mod_mbox/nifi-dev)). For more interactive discussions, community members can often be found in the following locations:
+
+- Apache NiFi Slack Workspace: https://apachenifi.slack.com/
+
+  New users can join the workspace using the following [invite link](https://join.slack.com/t/apachenifi/shared_invite/enQtNDI2NDMyMTY3MTA5LWJmZDI3MmM1ZmYyODQwZDYwM2MyMDY5ZjkyMDkxY2JmOGMyNmEzYTE0MTRkZTYwYzZlYTJkY2JhZTYyMzcyZGI).
+
+- IRC: #nifi on [irc.freenode.net](http://webchat.freenode.net/?channels=#nifi)
 
 ## License
 
@@ -57,4 +61,3 @@ 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.
-


[nifi-registry] 29/43: [NIFIREG-352] update frontend deps

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit f1e4fb2a872f82654792b430c57080f979358c09
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Thu Jan 2 20:17:54 2020 -0500

    [NIFIREG-352] update frontend deps
---
 .../src/main/package-lock.json                     | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
index 02d2452..fe0431f 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
@@ -8719,7 +8719,27 @@
             "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
             "dev": true,
             "requires": {
-                "handlebars": "^4.1.2"
+                "handlebars": "^4.1.0"
+            },
+            "dependencies": {
+                "handlebars": {
+                    "version": "4.5.3",
+                    "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
+                    "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
+                    "dev": true,
+                    "requires": {
+                        "neo-async": "^2.6.0",
+                        "optimist": "^0.6.1",
+                        "source-map": "^0.6.1",
+                        "uglify-js": "^3.1.4"
+                    }
+                },
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+                    "dev": true
+                }
             }
         },
         "jasmine": {


[nifi-registry] 35/43: NIFIREG-361 - Improved handling of the /access/logout endpoint.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 2d15b7da32d08726c2f6b6f5aaef86488c757e64
Author: Nathan Gough <th...@gmail.com>
AuthorDate: Thu Feb 13 17:24:47 2020 -0500

    NIFIREG-361 - Improved handling of the /access/logout endpoint.
---
 .../nifi/registry/web/api/AccessResource.java      | 38 ++++++++++++++
 .../nifi/registry/web/api/ApplicationResource.java |  9 ++++
 .../security/authentication/jwt/JwtService.java    | 14 +++++
 .../apache/nifi/registry/web/api/SecureLdapIT.java | 60 ++++++++++++++++++++++
 .../src/main/webapp/nf-registry.js                 | 17 +++++-
 .../src/main/webapp/services/nf-registry.api.js    | 31 +++++++++++
 6 files changed, 168 insertions(+), 1 deletion(-)

diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessResource.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessResource.java
index 30374f0..fd44ea4 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessResource.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/AccessResource.java
@@ -48,7 +48,9 @@ import org.springframework.lang.Nullable;
 import org.springframework.stereotype.Component;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -260,6 +262,42 @@ public class AccessResource extends ApplicationResource {
         return generateCreatedResponse(uri, token).build();
     }
 
+    @DELETE
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.WILDCARD)
+    @Path("/logout")
+    @ApiOperation(
+            value = "Performs a logout for other providers that have been issued a JWT.",
+            notes = NON_GUARANTEED_ENDPOINT
+    )
+    @ApiResponses(
+            value = {
+                    @ApiResponse(code = 200, message = "User was logged out successfully."),
+                    @ApiResponse(code = 401, message = "Authentication token provided was empty or not in the correct JWT format."),
+                    @ApiResponse(code = 500, message = "Client failed to log out."),
+            }
+    )
+    public Response logOut(@Context HttpServletRequest httpServletRequest, @Context HttpServletResponse httpServletResponse) {
+        if (!httpServletRequest.isSecure()) {
+            throw new IllegalStateException("User authentication/authorization is only supported when running over HTTPS.");
+        }
+
+        String userIdentity = NiFiUserUtils.getNiFiUserIdentity();
+
+        if(userIdentity != null && !userIdentity.isEmpty()) {
+            try {
+                logger.info("Logging out user " + userIdentity);
+                jwtService.logOut(userIdentity);
+                return generateOkResponse().build();
+            } catch (final JwtException e) {
+                logger.error("Logout of user " + userIdentity + " failed due to: " + e.getMessage());
+                return Response.serverError().build();
+            }
+        } else {
+            return Response.status(401, "Authentication token provided was empty or not in the correct JWT format.").build();
+        }
+    }
+
     @POST
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.TEXT_PLAIN)
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ApplicationResource.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ApplicationResource.java
index adabbfc..01b74ce 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ApplicationResource.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ApplicationResource.java
@@ -160,6 +160,15 @@ public class ApplicationResource {
     }
 
     /**
+     * Generates an Ok response with no content.
+     *
+     * @return an Ok response with no content
+     */
+    protected Response.ResponseBuilder generateOkResponse() {
+        return noCache(Response.ok());
+    }
+
+    /**
      * Generates a 201 Created response with the specified content.
      *
      * @param uri    The URI
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/jwt/JwtService.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/jwt/JwtService.java
index d47b301..d24e665 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/jwt/JwtService.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/security/authentication/jwt/JwtService.java
@@ -170,6 +170,20 @@ public class JwtService {
 
     }
 
+    public void logOut(String userIdentity) {
+        if (userIdentity == null || userIdentity.isEmpty()) {
+            throw new JwtException("Log out failed: The user identity was not present in the request token to log out user.");
+        }
+
+        try {
+            keyService.deleteKey(userIdentity);
+            logger.info("Deleted token from database.");
+        } catch (Exception e) {
+            logger.error("Unable to log out user: " + userIdentity + ". Failed to remove their token from database.");
+            throw e;
+        }
+    }
+
     private static long validateTokenExpiration(long proposedTokenExpiration, String identity) {
         final long maxExpiration = TimeUnit.MILLISECONDS.convert(12, TimeUnit.HOURS);
         final long minExpiration = TimeUnit.MILLISECONDS.convert(1, TimeUnit.MINUTES);
diff --git a/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java b/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java
index c6172a1..62b72ce 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/SecureLdapIT.java
@@ -85,6 +85,12 @@ public class SecureLdapIT extends IntegrationTestBase {
 
     private static final String tokenLoginPath = "access/token/login";
     private static final String tokenIdentityProviderPath = "access/token/identity-provider";
+    // A JWT signed by a key of 'secret'
+    private static final String SIGNED_BY_WRONG_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" +
+            ".eyJzdWIiOiJuaWZpYWRtaW4iLCJpc3MiOiJMZGFwSWRlbnRpdHlQcm92aWRlciIsImF1ZCI6IkxkYXB" +
+            "JZGVudGl0eVByb3ZpZGVyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoibmlmaWFkbWluIiwia2lkIjoiNDd" +
+            "lMjA1NzctY2I3Yi00M2MzLWFhOGYtZjI0ZDcyODQ3MDEwIiwiaWF0IjoxNTgxNTI5NTA1LCJleHAiOjE" +
+            "1ODE1NzI3MDV9.vvMpwLJt1w_6Id_tlS1knxTkJ2gv7_j5ySG6PmNjF0s";
 
     @TestConfiguration
     @Profile("ITSecureLdap")
@@ -288,6 +294,60 @@ public class SecureLdapIT extends IntegrationTestBase {
     }
 
     @Test
+    public void testLogout() {
+
+        // Given: the client is connected to an unsecured NiFi Registry
+        // and the /access endpoint is queried using a JWT for the nifiadmin LDAP user
+        final Response response = client
+                .target(createURL("/access"))
+                .request()
+                .header("Authorization", "Bearer " + adminAuthToken)
+                .get(Response.class);
+
+        // and the server returns a 200 OK with the expected current user
+        assertEquals(200, response.getStatus());
+
+        // When: the /access/logout endpoint with the JWT for the nifiadmin logs out the user
+        final Response logout_response = client
+                .target(createURL("/access/logout"))
+                .request()
+                .header("Authorization", "Bearer " + adminAuthToken)
+                .delete(Response.class);
+
+        assertEquals(200, logout_response.getStatus());
+
+        // Then: the /access endpoint is queried using the logged out JWT
+        final Response retryResponse = client
+                .target(createURL("/access"))
+                .request()
+                .header("Authorization", "Bearer " + adminAuthToken)
+                .get(Response.class);
+
+        // and the server returns a 401 Unauthorized as the user is now logged out
+        assertEquals(401, retryResponse.getStatus());
+        String retryJson = retryResponse.readEntity(String.class);
+        assertEquals("Unable to validate the access token. Contact the system administrator.\n", retryJson);
+
+        // Reset: We successfully logged out our user. Run setup to fix up the user, so the @After code can run to re-establish authorizations.
+        setup();
+    }
+
+    @Test
+    public void testLogoutWithJWTSignedByWrongKey() throws Exception {
+
+        // Given: use the /access/logout endpoint with the JWT for the nifiadmin LDAP user to log out
+        final Response logoutResponse = client
+                .target(createURL("/access"))
+                .request()
+                .header("Authorization", "Bearer " + SIGNED_BY_WRONG_KEY)
+                .delete(Response.class);
+
+        assertEquals(401, logoutResponse.getStatus());
+        String responseMessage = logoutResponse.readEntity(String.class);
+        assertEquals("Unable to validate the access token. Contact the system administrator.\n", responseMessage);
+    }
+
+    @Test
     public void testUsers() throws Exception {
 
         // Given: the client and server have been configured correctly for LDAP authentication
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
index 0ad0434..1bd5e28 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
@@ -71,9 +71,24 @@ NfRegistry.prototype = {
      * Invalidate old tokens and route to login page
      */
     logout: function () {
+    /**
+        $.ajax({
+            type: 'DELETE',
+            url: '../nifi-registry-api/access/logout',
+        }).done(function () {
+            delete this.nfRegistryService.currentUser.identity;
+            delete this.nfRegistryService.currentUser.anonymous;
+            this.nfStorage.removeItem('jwt');
+            this.router.navigateByUrl('login');
+        }).fail(nfErrorHandler.handleAjaxError);
+        **/
+
+
+        this.nfRegistryApi.deleteToLogout().subscribe(function () {
+
+        });
         delete this.nfRegistryService.currentUser.identity;
         delete this.nfRegistryService.currentUser.anonymous;
-        this.nfStorage.removeItem('jwt');
         this.router.navigateByUrl('login');
     },
 
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
index 8ec0c6a..a060630 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
@@ -703,6 +703,37 @@ NfRegistryApi.prototype = {
     },
 
     /**
+     * Logout a user.
+     *
+     * @returns {*}
+     */
+    deleteToLogout: function () {
+        var self = this;
+        var options = {
+            headers: headers,
+            withCredentials: true,
+            responseType: 'text'
+        };
+
+        return this.http.delete('../nifi-registry-api/access/logout', options).pipe(
+            map(function (response) {
+                // remove the token from local storage
+                self.nfStorage.removeItem('jwt');
+                return response;
+            }),
+            catchError(function (error) {
+                self.dialogService.openConfirm({
+                    title: 'Error',
+                    message: 'Please contact your System Administrator.',
+                    acceptButton: 'Ok',
+                    acceptButtonColor: 'fds-warn'
+                });
+                return of('');
+            })
+        );
+    },
+
+    /**
      * Kerberos ticket exchange.
      *
      * @returns {*}


[nifi-registry] 37/43: NIFIREG-361 - Fixed javascript as per code review. Tested with ldap, still logs out user as expected.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 1da08b1bf5e0aab1c9da902ba41563b1bc5da9bf
Author: Nathan Gough <th...@gmail.com>
AuthorDate: Fri Feb 21 14:24:05 2020 -0500

    NIFIREG-361 - Fixed javascript as per code review. Tested with ldap, still logs out user as expected.
    
    This closes #259
    
    Signed-off-by: Scott Aslan <sc...@gmail.com>
---
 .../src/main/webapp/nf-registry.js                 | 22 ++++++++++++++++------
 .../src/main/webapp/services/nf-registry.api.js    |  2 --
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
index 371b2de..79e97a8 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.js
@@ -71,12 +71,22 @@ NfRegistry.prototype = {
      * Invalidate old tokens and route to login page
      */
     logout: function () {
-        this.nfRegistryApi.deleteToLogout().subscribe(function () {
-
-        });
-        delete this.nfRegistryService.currentUser.identity;
-        delete this.nfRegistryService.currentUser.anonymous;
-        this.router.navigateByUrl('login');
+        var self = this;
+        self.nfRegistryApi.deleteToLogout().subscribe(
+            function () {
+                // next call
+            },
+            function () {
+                // error callback
+            },
+            function () {
+                // complete callback... clean up and navigate on complete only
+                self.nfStorage.removeItem('jwt');
+                delete self.nfRegistryService.currentUser.identity;
+                delete self.nfRegistryService.currentUser.anonymous;
+                self.router.navigateByUrl('login');
+            }
+        );
     },
 
     /**
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
index a060630..041a0a1 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/services/nf-registry.api.js
@@ -717,8 +717,6 @@ NfRegistryApi.prototype = {
 
         return this.http.delete('../nifi-registry-api/access/logout', options).pipe(
             map(function (response) {
-                // remove the token from local storage
-                self.nfStorage.removeItem('jwt');
                 return response;
             }),
             catchError(function (error) {


[nifi-registry] 10/43: NIFIREG-327 Added section on recommended antivirus exclusions to Admin Guide

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 7e2f120a172b138c083faad44872090ca3fe1a59
Author: Andrew Lim <an...@gmail.com>
AuthorDate: Tue Oct 8 16:08:06 2019 -0400

    NIFIREG-327 Added section on recommended antivirus exclusions to Admin Guide
---
 .../src/main/asciidoc/administration-guide.adoc                | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
index b9bc1df..0c6a5dd 100644
--- a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
@@ -66,6 +66,16 @@ When NiFi Registry first starts up, the following directories are created:
 
 See the <<system_properties>> section of this guide for more information about NiFi Registry configuration files.
 
+== Recommended Antivirus Exclusions
+Antivirus software can take a long time to scan large directories and the numerous files within them. Additionally, if the antivirus software locks files or directories during a scan, those resources are unavailable to NiFi Registry processes, causing latency or unavailability of these resources in a NiFi Registry instance. To prevent these performance and reliability issues from occurring, it is highly recommended to configure your antivirus software to skip scans on the following NiFi  [...]
+
+* `database`
+* `extension_bundles`
+* `flow_storage`
+* `logs`
+
+NOTE: The directories listed are generated at startup for a default NiFi Registry installation. Consider your configuration when determining directories to exclude during antivirus scans. For example, if an external database has been setup or if a different flow storage directory is specified in your configuration.
+
 [[security_configuration]]
 == Security Configuration
 


[nifi-registry] 21/43: NIFIREG-345 Bump ranger-client version to 2.0.0

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 5e66a21ec5490721397626cd17e6e958476f4d95
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Fri Nov 8 14:08:39 2019 -0500

    NIFIREG-345 Bump ranger-client version to 2.0.0
    
    This closes #247
---
 .../nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml          | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml
index 75bf3a1..e75681a 100644
--- a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml
+++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml
@@ -25,8 +25,8 @@
     <packaging>jar</packaging>
 
     <properties>
-        <ranger.version>1.1.0</ranger.version>
-        <ranger.hadoop.version>3.0.0</ranger.hadoop.version>
+        <ranger.version>2.0.0</ranger.version>
+        <ranger.hadoop.version>3.1.1</ranger.hadoop.version>
     </properties>
 
     <dependencies>


[nifi-registry] 40/43: NIFIREG-348 Update NiFi logo and ico file

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit c15ae9eea0510d35f323024e701568e27b03e7c4
Author: Andrew Lim <an...@gmail.com>
AuthorDate: Fri Nov 22 13:32:18 2019 -0500

    NIFIREG-348 Update NiFi logo and ico file
    
    Signed-off-by: Pierre Villard <pi...@gmail.com>
    
    This closes #249.
---
 .../src/main/resources/images/bgNifiLogo.png          | Bin 3894 -> 5931 bytes
 .../src/main/resources/images/nifi16.ico              | Bin 1150 -> 1150 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png b/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png
index 2558d43..1e12fee 100644
Binary files a/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png and b/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/bgNifiLogo.png differ
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/nifi16.ico b/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/nifi16.ico
index 2ac3670..12da810 100644
Binary files a/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/nifi16.ico and b/nifi-registry-core/nifi-registry-web-api/src/main/resources/images/nifi16.ico differ


[nifi-registry] 19/43: [NIFIREG-324] add hammerJS to testbed

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 5cb04c60796b49c39e05ed3510181915c8924de3
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Thu Oct 3 10:58:38 2019 -0400

    [NIFIREG-324] add hammerJS to testbed
    
    This closes #234.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 .../nifi-registry-web-ui/src/main/webapp/nf-registry.testbed-factory.js  | 1 +
 1 file changed, 1 insertion(+)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.testbed-factory.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.testbed-factory.js
index d71a858..cc19528 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.testbed-factory.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/nf-registry.testbed-factory.js
@@ -24,6 +24,7 @@ import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
 import { HttpClientTestingModule } from '@angular/common/http/testing';
 import { MomentModule } from 'angular2-moment';
 
+import 'hammerjs';
 import NfRegistryRoutes from 'nf-registry.routes';
 import { APP_BASE_HREF } from '@angular/common';
 import { FdsCoreModule } from '@nifi-fds/core';


[nifi-registry] 23/43: update package-lock

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit bb3b2911dcfb00413397d208a698bf704822b0cd
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Thu Jan 2 21:29:39 2020 -0500

    update package-lock
---
 .../src/main/package-lock.json                     | 145 ++++++---------------
 1 file changed, 41 insertions(+), 104 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
index ada8c0a..02d2452 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/package-lock.json
@@ -4753,6 +4753,43 @@
             "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
             "dev": true
         },
+        "escodegen": {
+            "version": "1.8.1",
+            "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
+            "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
+            "dev": true,
+            "requires": {
+                "esprima": "^2.7.1",
+                "estraverse": "^1.9.1",
+                "esutils": "^2.0.2",
+                "optionator": "^0.8.1",
+                "source-map": "~0.2.0"
+            },
+            "dependencies": {
+                "esprima": {
+                    "version": "2.7.3",
+                    "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+                    "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+                    "dev": true
+                },
+                "estraverse": {
+                    "version": "1.9.3",
+                    "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
+                    "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
+                    "dev": true
+                },
+                "source-map": {
+                    "version": "0.2.0",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
+                    "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
+                    "dev": true,
+                    "optional": true,
+                    "requires": {
+                        "amdefine": ">=0.0.4"
+                    }
+                }
+            }
+        },
         "eslint": {
             "version": "5.14.1",
             "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.14.1.tgz",
@@ -8437,37 +8474,12 @@
                     "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=",
                     "dev": true
                 },
-                "async": {
-                    "version": "1.5.2",
-                    "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
-                    "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
-                    "dev": true
-                },
-                "escodegen": {
-                    "version": "1.8.1",
-                    "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
-                    "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
-                    "dev": true,
-                    "requires": {
-                        "esprima": "^2.7.1",
-                        "estraverse": "^1.9.1",
-                        "esutils": "^2.0.2",
-                        "optionator": "^0.8.1",
-                        "source-map": "~0.2.0"
-                    }
-                },
                 "esprima": {
                     "version": "2.7.3",
                     "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
                     "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
                     "dev": true
                 },
-                "estraverse": {
-                    "version": "1.9.3",
-                    "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
-                    "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=",
-                    "dev": true
-                },
                 "glob": {
                     "version": "5.0.15",
                     "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
@@ -8481,52 +8493,6 @@
                         "path-is-absolute": "^1.0.0"
                     }
                 },
-                "js-yaml": {
-                    "version": "3.13.1",
-                    "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-                    "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
-                    "dev": true,
-                    "requires": {
-                        "argparse": "^1.0.7",
-                        "esprima": "^4.0.0"
-                    },
-                    "dependencies": {
-                        "esprima": {
-                            "version": "4.0.1",
-                            "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-                            "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-                            "dev": true
-                        }
-                    }
-                },
-                "minimatch": {
-                    "version": "3.0.4",
-                    "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-                    "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
-                    "dev": true,
-                    "requires": {
-                        "brace-expansion": "^1.1.7"
-                    }
-                },
-                "nopt": {
-                    "version": "3.0.6",
-                    "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
-                    "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
-                    "dev": true,
-                    "requires": {
-                        "abbrev": "1"
-                    }
-                },
-                "source-map": {
-                    "version": "0.2.0",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz",
-                    "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=",
-                    "dev": true,
-                    "optional": true,
-                    "requires": {
-                        "amdefine": ">=0.0.4"
-                    }
-                },
                 "supports-color": {
                     "version": "3.2.3",
                     "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
@@ -8536,15 +8502,6 @@
                         "has-flag": "^1.0.0"
                     }
                 },
-                "which": {
-                    "version": "1.3.0",
-                    "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
-                    "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=",
-                    "dev": true,
-                    "requires": {
-                        "isexe": "^2.0.0"
-                    }
-                },
                 "wordwrap": {
                     "version": "1.0.0",
                     "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
@@ -8757,32 +8714,12 @@
             }
         },
         "istanbul-reports": {
-            "version": "2.2.3",
-            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.3.tgz",
-            "integrity": "sha512-T6EbPuc8Cb620LWAYyZ4D8SSn06dY9i1+IgUX2lTH8gbwflMc9Obd33zHTyNX653ybjpamAHS9toKS3E6cGhTw==",
+            "version": "2.2.6",
+            "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz",
+            "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==",
             "dev": true,
             "requires": {
-                "handlebars": "^4.1.0"
-            },
-            "dependencies": {
-                "handlebars": {
-                    "version": "4.5.3",
-                    "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz",
-                    "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==",
-                    "dev": true,
-                    "requires": {
-                        "neo-async": "^2.6.0",
-                        "optimist": "^0.6.1",
-                        "source-map": "^0.6.1",
-                        "uglify-js": "^3.1.4"
-                    }
-                },
-                "source-map": {
-                    "version": "0.6.1",
-                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-                    "dev": true
-                }
+                "handlebars": "^4.1.2"
             }
         },
         "jasmine": {


[nifi-registry] 07/43: NIFIREG-323 Clear secret key when auto restarting in order to obtain new secret key from the NiFi Registry process

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 17dcc776c8807e48f2d9953016c352176acc3482
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Mon Sep 30 15:13:19 2019 -0400

    NIFIREG-323 Clear secret key when auto restarting in order to obtain new secret key from the NiFi Registry process
---
 .../main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java    | 1 +
 1 file changed, 1 insertion(+)

diff --git a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
index e7a46b7..af11fa4 100644
--- a/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
+++ b/nifi-registry-core/nifi-registry-bootstrap/src/main/java/org/apache/nifi/registry/bootstrap/RunNiFiRegistry.java
@@ -1055,6 +1055,7 @@ public class RunNiFiRegistry {
                     }
 
                     defaultLogger.warn("Apache NiFi Registry appears to have died. Restarting...");
+                    secretKey = null;
                     process = builder.start();
                     handleLogging(process);
 


[nifi-registry] 03/43: Update .travis.yml

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 75b188a276ca364dc7242db4f6b2052f9e46efd9
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Wed Sep 4 15:01:46 2019 -0400

    Update .travis.yml
---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index a85ddbd..1cfe9be 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,5 +57,5 @@ install: true
 
 #build commands
 script:
-    - mvn -T 2C clean install -Pintegration-tests,contrib-check,jsUnitTests | grep -v -F -f .travis-output-filters && exit ${PIPESTATUS[0]}
+    - mvn clean install -Pintegration-tests,contrib-check,jsUnitTests | grep -v -F -f .travis-output-filters && exit ${PIPESTATUS[0]}
 


[nifi-registry] 25/43: NIFIREG-355 Adding profiles to optionally include addtional hadoop libs in ext/ranger/lib

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit dab4b5f120b4d1ee2ef5ec7cb0c943caf3bc534b
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Thu Jan 23 15:21:03 2020 -0500

    NIFIREG-355 Adding profiles to optionally include addtional hadoop libs in ext/ranger/lib
---
 .../nifi-registry-ranger-plugin/pom.xml            | 66 ++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml
index e75681a..e05914c 100644
--- a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml
+++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-plugin/pom.xml
@@ -212,4 +212,70 @@
 
     </dependencies>
 
+    <profiles>
+        <!-- Includes hadoop-aws for accessing HDFS with an s3a:// filesystem -->
+        <profile>
+            <id>include-hadoop-aws</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.hadoop</groupId>
+                    <artifactId>hadoop-aws</artifactId>
+                    <version>${ranger.hadoop.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+        <!-- Includes hadoop-azure and hadoop-azure-datalake for accessing HDFS with wasb://, abfs://, and adl:// filesystems -->
+        <profile>
+            <id>include-hadoop-azure</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.hadoop</groupId>
+                    <artifactId>hadoop-azure</artifactId>
+                    <version>${ranger.hadoop.version}</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>com.google.guava</groupId>
+                            <artifactId>guava</artifactId>
+                        </exclusion>
+                        <exclusion>
+                            <groupId>com.fasterxml.jackson.core</groupId>
+                            <artifactId>jackson-core</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+                <dependency>
+                    <groupId>org.apache.hadoop</groupId>
+                    <artifactId>hadoop-azure-datalake</artifactId>
+                    <version>${ranger.hadoop.version}</version>
+                    <exclusions>
+                        <exclusion>
+                            <groupId>com.fasterxml.jackson.core</groupId>
+                            <artifactId>jackson-core</artifactId>
+                        </exclusion>
+                    </exclusions>
+                </dependency>
+            </dependencies>
+        </profile>
+        <!-- Includes hadoop-cloud-storage -->
+        <profile>
+            <id>include-hadoop-cloud-storage</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.hadoop</groupId>
+                    <artifactId>hadoop-cloud-storage</artifactId>
+                    <version>${ranger.hadoop.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
+    </profiles>
+
 </project>
\ No newline at end of file


[nifi-registry] 38/43: Add prop_replace command to update nifi.registry.security.keyPasswd using either the KEY_PASSWORD or KEYSTORE_PASSWORD environment variable

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 42acd047104644ff70f4e52e33217d9ad03a60a4
Author: Justin Rittenhouse <jr...@nd.edu>
AuthorDate: Wed Mar 4 11:30:21 2020 -0500

    Add prop_replace command to update nifi.registry.security.keyPasswd using either the KEY_PASSWORD or KEYSTORE_PASSWORD environment variable
    
    Signed-off-by: Pierre Villard <pi...@gmail.com>
    
    This closes #264.
---
 nifi-registry-core/nifi-registry-docker/dockerhub/sh/secure.sh | 1 +
 nifi-registry-docker-maven/dockermaven/sh/secure.sh            | 1 +
 2 files changed, 2 insertions(+)

diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/sh/secure.sh b/nifi-registry-core/nifi-registry-docker/dockerhub/sh/secure.sh
index 352dfad..8a7a5bb 100644
--- a/nifi-registry-core/nifi-registry-docker/dockerhub/sh/secure.sh
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/sh/secure.sh
@@ -41,6 +41,7 @@ fi
 prop_replace 'nifi.registry.security.keystore'           "${KEYSTORE_PATH}"
 prop_replace 'nifi.registry.security.keystoreType'       "${KEYSTORE_TYPE}"
 prop_replace 'nifi.registry.security.keystorePasswd'     "${KEYSTORE_PASSWORD}"
+prop_replace 'nifi.registry.security.keyPasswd'          "${KEY_PASSWORD:-$KEYSTORE_PASSWORD}"
 prop_replace 'nifi.registry.security.truststore'         "${TRUSTSTORE_PATH}"
 prop_replace 'nifi.registry.security.truststoreType'     "${TRUSTSTORE_TYPE}"
 prop_replace 'nifi.registry.security.truststorePasswd'   "${TRUSTSTORE_PASSWORD}"
diff --git a/nifi-registry-docker-maven/dockermaven/sh/secure.sh b/nifi-registry-docker-maven/dockermaven/sh/secure.sh
index 352dfad..8a7a5bb 100644
--- a/nifi-registry-docker-maven/dockermaven/sh/secure.sh
+++ b/nifi-registry-docker-maven/dockermaven/sh/secure.sh
@@ -41,6 +41,7 @@ fi
 prop_replace 'nifi.registry.security.keystore'           "${KEYSTORE_PATH}"
 prop_replace 'nifi.registry.security.keystoreType'       "${KEYSTORE_TYPE}"
 prop_replace 'nifi.registry.security.keystorePasswd'     "${KEYSTORE_PASSWORD}"
+prop_replace 'nifi.registry.security.keyPasswd'          "${KEY_PASSWORD:-$KEYSTORE_PASSWORD}"
 prop_replace 'nifi.registry.security.truststore'         "${TRUSTSTORE_PATH}"
 prop_replace 'nifi.registry.security.truststoreType'     "${TRUSTSTORE_TYPE}"
 prop_replace 'nifi.registry.security.truststorePasswd'   "${TRUSTSTORE_PASSWORD}"


[nifi-registry] 12/43: NIFIREG-336 Enable Integration Tests by Default

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 9849f85dda796db7d097a05a40c2691d5e4fcc37
Author: Kevin Doran <kd...@apache.org>
AuthorDate: Wed Oct 16 13:15:03 2019 -0400

    NIFIREG-336 Enable Integration Tests by Default
---
 .travis.yml |  2 +-
 README.md   |  4 ----
 pom.xml     | 24 ++++++++++++++++--------
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 1cfe9be..e83abde 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -57,5 +57,5 @@ install: true
 
 #build commands
 script:
-    - mvn clean install -Pintegration-tests,contrib-check,jsUnitTests | grep -v -F -f .travis-output-filters && exit ${PIPESTATUS[0]}
+    - mvn clean install -Pcontrib-check,jsUnitTests | grep -v -F -f .travis-output-filters && exit ${PIPESTATUS[0]}
 
diff --git a/README.md b/README.md
index b280201..98868bf 100644
--- a/README.md
+++ b/README.md
@@ -42,10 +42,6 @@ Registry—a subproject of Apache NiFi—is a complementary application that pro
     If you wish to enable style and license checks, specify the contrib-check profile:
     
         mvn clean install -Pcontrib-check
-        
-    If you wish to run integration tests and contrib-check, specify both profiles:
-    
-        mvn clean install -Pcontrib-check,integration-tests
 
 3) Start the application
 
diff --git a/pom.xml b/pom.xml
index e97bc60..cfa73af 100644
--- a/pom.xml
+++ b/pom.xml
@@ -588,6 +588,19 @@
                 </configuration>
             </plugin>
             <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                        <phase>verify</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
                 <groupId>org.apache.rat</groupId>
                 <artifactId>apache-rat-plugin</artifactId>
                 <configuration>
@@ -664,13 +677,8 @@
             </build>
         </profile>
         <profile>
-            <!-- Performs execution of Integration Tests using the Maven
-                FailSafe Plugin. The view of integration tests in this context are those
-                tests loading a full web server with API war with no mocks. -->
-            <id>integration-tests</id>
-            <activation>
-                <activeByDefault>true</activeByDefault>
-            </activation>
+            <!-- Disables execution of integration tests managed by the Maven FailSafe plugin. -->
+            <id>no-integration-tests</id>
             <build>
                 <plugins>
                     <plugin>
@@ -682,7 +690,7 @@
                                     <goal>integration-test</goal>
                                     <goal>verify</goal>
                                 </goals>
-                                <phase>verify</phase>
+                                <phase>none</phase>
                             </execution>
                         </executions>
                     </plugin>


[nifi-registry] 43/43: Fix docker maven files

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 511b88611e85e02ec8625816a13c88ad2bf15f25
Author: Arpad Boda <ab...@apache.org>
AuthorDate: Tue Mar 17 18:17:39 2020 +0100

    Fix docker maven files
---
 nifi-registry-docker-maven/dockermaven/pom.xml | 4 ++--
 nifi-registry-docker-maven/pom.xml             | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/nifi-registry-docker-maven/dockermaven/pom.xml b/nifi-registry-docker-maven/dockermaven/pom.xml
index 4b00044..9716d37 100644
--- a/nifi-registry-docker-maven/dockermaven/pom.xml
+++ b/nifi-registry-docker-maven/dockermaven/pom.xml
@@ -15,9 +15,9 @@
     <parent>
         <artifactId>nifi-registry-docker-maven</artifactId>
         <groupId>org.apache.nifi.registry</groupId>
-        <version>1.0.0-SNAPSHOT</version>
+        <version>0.6.0-SNAPSHOT</version>
     </parent>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>0.6.0-SNAPSHOT</version>
 
     <artifactId>dockermaven</artifactId>
 
diff --git a/nifi-registry-docker-maven/pom.xml b/nifi-registry-docker-maven/pom.xml
index 3e9b405..6689144 100644
--- a/nifi-registry-docker-maven/pom.xml
+++ b/nifi-registry-docker-maven/pom.xml
@@ -17,7 +17,7 @@
     <parent>
         <groupId>org.apache.nifi.registry</groupId>
         <artifactId>nifi-registry</artifactId>
-        <version>1.0.0-SNAPSHOT</version>
+        <version>0.6.0-SNAPSHOT</version>
     </parent>
     
     <modelVersion>4.0.0</modelVersion>
@@ -25,7 +25,7 @@
     
     <artifactId>nifi-registry-docker-maven</artifactId>
     <groupId>org.apache.nifi.registry</groupId>
-    <version>1.0.0-SNAPSHOT</version>
+    <version>0.6.0-SNAPSHOT</version>
 
     <modules>
         <module>dockermaven</module>


[nifi-registry] 08/43: [NIFIREG-319] remove code coverage instrumentation from nifi-fds js modules

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 25625cdbbd04e535970792cf3b628a5fbd2b3f62
Author: Scott Aslan <sc...@gmail.com>
AuthorDate: Wed Sep 18 15:25:38 2019 -0400

    [NIFIREG-319] remove code coverage instrumentation from nifi-fds js modules
    
    This closes #229.
---
 .../nifi-registry-web-ui/src/main/webpack.karma.js |  1 +
 .../src/main/webpack.loader.js                     | 27 ++++++++++++++++++++--
 2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js
index 01eb073..c1fee77 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.karma.js
@@ -30,6 +30,7 @@ module.exports = merge(commonConfig, {
 
     module: {
         rules: [
+            loaders.jsFDS,
             loaders.tsCoverage,
             loaders.jsCoverage,
             loaders.html,
diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js
index 5014a98..c424893 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webpack.loader.js
@@ -88,12 +88,35 @@ module.exports = {
         ]
     },
 
-    jsCoverage: {
+    jsFDS: {
         test: /\.js$/,
         include: [
-            path.resolve(__dirname, 'webapp'),
             path.resolve(__dirname, 'node_modules/@nifi-fds/core')
         ],
+        use: [
+            {
+                loader: 'cache-loader',
+                options: {
+                    cacheDirectory: cacheCoverageDir
+                }
+            },
+            {
+                loader: path.resolve(__dirname, 'angular-url-loader')
+            },
+            {
+                loader: 'babel-loader',
+                options: {
+                    presets: ['@babel/preset-env']
+                }
+            }
+        ]
+    },
+
+    jsCoverage: {
+        test: /\.js$/,
+        include: [
+            path.resolve(__dirname, 'webapp')
+        ],
         // prevent these files/patterns from being included in the coverage report
         exclude: [
             /\.spec\.js$/,


[nifi-registry] 31/43: NIFIREG-362 - Updated dependencies and ran tests. Smoke tested NiFi and NiFi Reg in secured instances.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 46bb1aa603c78aaa0e34e8bc75f31ac6358dae8a
Author: Nathan Gough <th...@gmail.com>
AuthorDate: Fri Feb 14 12:57:15 2020 -0500

    NIFIREG-362 - Updated dependencies and ran tests. Smoke tested NiFi and NiFi Reg in secured instances.
    
    This closes #260.
    
    Signed-off-by: Andy LoPresto <al...@apache.org>
---
 nifi-registry-core/nifi-registry-framework/pom.xml | 2 +-
 pom.xml                                            | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-framework/pom.xml b/nifi-registry-core/nifi-registry-framework/pom.xml
index da26284..842a2e8 100644
--- a/nifi-registry-core/nifi-registry-framework/pom.xml
+++ b/nifi-registry-core/nifi-registry-framework/pom.xml
@@ -295,7 +295,7 @@
         <dependency>
             <groupId>org.eclipse.jgit</groupId>
             <artifactId>org.eclipse.jgit</artifactId>
-            <version>4.11.8.201904181247-r</version>
+            <version>4.11.9.201909030838-r</version>
         </dependency>
         <dependency>
             <groupId>commons-codec</groupId>
diff --git a/pom.xml b/pom.xml
index 74067bd..d6c5161 100644
--- a/pom.xml
+++ b/pom.xml
@@ -96,14 +96,14 @@
         <jax.rs.api.version>2.1</jax.rs.api.version>
         <jersey.version>2.27</jersey.version>
         <jackson.version>2.9.9</jackson.version>
-        <jackson.databind.version>2.9.9.1</jackson.databind.version>
-        <spring.boot.version>2.1.6.RELEASE</spring.boot.version>
-        <spring.security.version>5.1.5.RELEASE</spring.security.version>
+        <jackson.databind.version>2.9.10.2</jackson.databind.version>
+        <spring.boot.version>2.1.12.RELEASE</spring.boot.version>
+        <spring.security.version>5.1.8.RELEASE</spring.security.version>
         <flyway.version>5.2.4</flyway.version>
         <flyway.tests.version>5.1.0</flyway.tests.version>
         <swagger.ui.version>3.12.0</swagger.ui.version>
         <testcontainers.version>1.11.2</testcontainers.version>
-	    <h2.version>1.4.197</h2.version>
+	    <h2.version>1.4.200</h2.version>
         <groovy.version>2.5.4</groovy.version>
         <groovy.eclipse.compiler.version>3.4.0-01</groovy.eclipse.compiler.version>
         <jaxb.version>2.3.2</jaxb.version>


[nifi-registry] 15/43: NIFIREG-338: fixing version in dockerfile

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 6a3dbd26ee83163fbaa12cf4ca6373905f5684a8
Author: Endre Zoltan Kovacs <an...@protonmail.com>
AuthorDate: Fri Oct 18 09:52:39 2019 +0200

    NIFIREG-338: fixing version in dockerfile
---
 nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile b/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile
index 0d48e18..5fabb95 100644
--- a/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile
+++ b/nifi-registry-core/nifi-registry-docker/dockerhub/Dockerfile
@@ -22,7 +22,7 @@ LABEL site="https://nifi.apache.org"
 
 ARG UID=1000
 ARG GID=1000
-ARG NIFI_REGISTRY_VERSION=0.6.0
+ARG NIFI_REGISTRY_VERSION=1.0.0
 ARG MIRROR=https://archive.apache.org/dist
 
 ENV NIFI_REGISTRY_BASE_DIR /opt/nifi-registry


[nifi-registry] 13/43: NIFIREG-329 Add build profile that tests all DBs

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit e171ba9ca5c7f512e991418ab77955fec1735e6e
Author: Kevin Doran <kd...@apache.org>
AuthorDate: Wed Oct 16 13:01:22 2019 -0400

    NIFIREG-329 Add build profile that tests all DBs
    
    This closes #240.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 README.md                  | 34 +++++++++--------------
 nifi-registry-core/pom.xml | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 81 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index 98868bf..4999a69 100644
--- a/README.md
+++ b/README.md
@@ -64,31 +64,23 @@ Registry—a subproject of Apache NiFi—is a complementary application that pro
 
 ## Database Testing
 
-In order to ensure that NiFi Registry works correctly against different relational databases, the existing integration tests can be run against different databases by leveraging the [Testcontainers framework](https://www.testcontainers.org/).
+In order to ensure that NiFi Registry works correctly against different relational databases, 
+the existing integration tests can be run against different databases by leveraging the [Testcontainers framework](https://www.testcontainers.org/).
 
-Spring profiles are used to control the DataSource factory that will be made available to the Spring application context. DataSource factories are provided that use the Testcontainers framework to start a Docker container for a given database and create a corresponding DataSource. If no profile is specified then an H2 DataSource will be used by default and no Docker containers are required.
+Spring profiles are used to control the DataSource factory that will be made available to the Spring application context. 
+DataSource factories are provided that use the Testcontainers framework to start a Docker container for a given database and create a corresponding DataSource. 
+If no profile is specified then an H2 DataSource will be used by default and no Docker containers are required.
 
 Assuming Docker is running on the system where the build is running, then the following commands can be run:
 
-* H2 (default)
-    
-      mvn clean install -Pcontrib-check,integration-tests
-      
-* Postgres
-
-      mvn clean install -Pcontrib-check,integration-tests -Dspring.profiles.active=postgres
-      
-* MySQL 5.6
-
-      mvn clean install -Pcontrib-check,integration-tests -Dspring.profiles.active=mysql-56
-      
-* MySQL 5.7
-
-      mvn clean install -Pcontrib-check,integration-tests -Dspring.profiles.active=mysql-57
-      
-* MySQL 8.0
-
-      mvn clean install -Pcontrib-check,integration-tests -Dspring.profiles.active=mysql-8
+| Target Database | Build Command | 
+| --------------- | ------------- |
+| All supported   | `mvn verify -Ptest-all-dbs` |
+| H2 (default)    | `mvn verify` |
+| PostgreSQL      | `mvn verify -Dspring.profiles.active=postgres` | 
+| MySQL 5.6       | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-56` |
+| MySQL 5.7       | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-57` |
+| MySQL 8         | `mvn verify -Pcontrib-check -Dspring.profiles.active=mysql-8`  |
       
  When one of the Testcontainer profiles is activated, the test output should show logs that indicate a container has been started, such as the following:
  
diff --git a/nifi-registry-core/pom.xml b/nifi-registry-core/pom.xml
index 570c695..b69059e 100644
--- a/nifi-registry-core/pom.xml
+++ b/nifi-registry-core/pom.xml
@@ -146,4 +146,72 @@
         </dependencies>
     </dependencyManagement>
 
+    <profiles>
+        <profile>
+            <id>test-all-dbs</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>mysql5.6-test</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <spring.profiles.active>mysql-56</spring.profiles.active>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>mysql5.7-test</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <spring.profiles.active>mysql-57</spring.profiles.active>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>mysql58-test</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <spring.profiles.active>mysql-8</spring.profiles.active>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                            <execution>
+                                <id>postgres-test</id>
+                                <phase>verify</phase>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                                <configuration>
+                                    <systemPropertyVariables>
+                                        <spring.profiles.active>postgres</spring.profiles.active>
+                                    </systemPropertyVariables>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
 </project>


[nifi-registry] 26/43: NIFIREG-353 Add ShellUserGroupProvider and relax checks to allow a user to have same identity as a group

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 23afadfcb91cc7253b6a7d3caa8db2e671132a94
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Thu Jan 23 13:18:51 2020 -0500

    NIFIREG-353 Add ShellUserGroupProvider and relax checks to allow a user to have same identity as a group
    
    This closes #255.
---
 .../security/authorization/AuthorizerFactory.java  |  18 +-
 .../authorization/shell/NssShellCommands.java      |  89 +++
 .../authorization/shell/OsxShellCommands.java      |  81 +++
 .../authorization/shell/RemoteShellCommands.java   |  73 +++
 .../authorization/shell/ShellCommandsProvider.java | 100 +++
 .../security/authorization/shell/ShellRunner.java  |  81 +++
 .../shell/ShellUserGroupProvider.java              | 678 +++++++++++++++++++++
 ...gistry.security.authorization.UserGroupProvider |   3 +-
 .../src/main/resources/conf/authorizers.xml        |  19 +
 .../org/apache/nifi/registry/util/FormatUtils.java | 232 ++++++-
 10 files changed, 1334 insertions(+), 40 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
index 916892b..a819e97 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java
@@ -611,7 +611,7 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
 
                                 @Override
                                 public User addUser(User user) throws AuthorizationAccessException {
-                                    if (tenantExists(baseConfigurableUserGroupProvider, user.getIdentifier(), user.getIdentity())) {
+                                    if (userExists(baseConfigurableUserGroupProvider, user.getIdentifier(), user.getIdentity())) {
                                         throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", user.getIdentity()));
                                     }
                                     return baseConfigurableUserGroupProvider.addUser(user);
@@ -624,7 +624,7 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
 
                                 @Override
                                 public User updateUser(User user) throws AuthorizationAccessException {
-                                    if (tenantExists(baseConfigurableUserGroupProvider, user.getIdentifier(), user.getIdentity())) {
+                                    if (userExists(baseConfigurableUserGroupProvider, user.getIdentifier(), user.getIdentity())) {
                                         throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", user.getIdentity()));
                                     }
                                     if (!baseConfigurableUserGroupProvider.isConfigurable(user)) {
@@ -651,7 +651,7 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
 
                                 @Override
                                 public Group addGroup(Group group) throws AuthorizationAccessException {
-                                    if (tenantExists(baseConfigurableUserGroupProvider, group.getIdentifier(), group.getName())) {
+                                    if (groupExists(baseConfigurableUserGroupProvider, group.getIdentifier(), group.getName())) {
                                         throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", group.getName()));
                                     }
                                     if (!allGroupUsersExist(baseUserGroupProvider, group)) {
@@ -667,7 +667,7 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
 
                                 @Override
                                 public Group updateGroup(Group group) throws AuthorizationAccessException {
-                                    if (tenantExists(baseConfigurableUserGroupProvider, group.getIdentifier(), group.getName())) {
+                                    if (groupExists(baseConfigurableUserGroupProvider, group.getIdentifier(), group.getName())) {
                                         throw new IllegalStateException(String.format("User/user group already exists with the identity '%s'.", group.getName()));
                                     }
                                     if (!baseConfigurableUserGroupProvider.isConfigurable(group)) {
@@ -796,14 +796,14 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
 
             // ensure that only one group exists per identity
             for (User user : userGroupProvider.getUsers()) {
-                if (tenantExists(userGroupProvider, user.getIdentifier(), user.getIdentity())) {
+                if (userExists(userGroupProvider, user.getIdentifier(), user.getIdentity())) {
                     throw new SecurityProviderCreationException(String.format("Found multiple users/user groups with identity '%s'.", user.getIdentity()));
                 }
             }
 
             // ensure that only one group exists per identity
             for (Group group : userGroupProvider.getGroups()) {
-                if (tenantExists(userGroupProvider, group.getIdentifier(), group.getName())) {
+                if (groupExists(userGroupProvider, group.getIdentifier(), group.getName())) {
                     throw new SecurityProviderCreationException(String.format("Found multiple users/user groups with name '%s'.", group.getName()));
                 }
             }
@@ -896,7 +896,7 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
      * @param identity identity of the tenant
      * @return true if another user exists with the same identity, false otherwise
      */
-    private static boolean tenantExists(final UserGroupProvider userGroupProvider, final String identifier, final String identity) {
+    private static boolean userExists(final UserGroupProvider userGroupProvider, final String identifier, final String identity) {
         for (User user : userGroupProvider.getUsers()) {
             if (!user.getIdentifier().equals(identifier)
                     && user.getIdentity().equals(identity)) {
@@ -904,6 +904,10 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP
             }
         }
 
+        return false;
+    }
+
+    private static boolean groupExists(final UserGroupProvider userGroupProvider, final String identifier, final String identity) {
         for (Group group : userGroupProvider.getGroups()) {
             if (!group.getIdentifier().equals(identifier)
                     && group.getName().equals(identity)) {
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/NssShellCommands.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/NssShellCommands.java
new file mode 100644
index 0000000..eef58b0
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/NssShellCommands.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.shell;
+
+/**
+ * Provides shell commands to read users and groups on NSS-enabled systems.
+ *
+ * See `man 5 nsswitch.conf` for more info.
+ */
+class NssShellCommands implements ShellCommandsProvider {
+    /**
+     * @return Shell command string that will return a list of users.
+     */
+    public String getUsersList() {
+        return "getent passwd | cut -f 1,3,4 -d ':'";
+    }
+
+    /**
+     * @return Shell command string that will return a list of groups.
+     */
+    public String getGroupsList() {
+        return "getent group | cut -f 1,3 -d ':'";
+    }
+
+    /**
+     * @param groupName name of group.
+     * @return Shell command string that will return a list of users for a group.
+     */
+    public String getGroupMembers(String groupName) {
+        return String.format("getent group %s | cut -f 4 -d ':'", groupName);
+    }
+
+    /**
+     * Gets the command for reading a single user by id.
+     *
+     * When executed, this command should output a single line, in the format used by `getUsersList`.
+     *
+     * @param userId name of user.
+     * @return Shell command string that will read a single user.
+     */
+    @Override
+    public String getUserById(String userId) {
+        return String.format("getent passwd %s | cut -f 1,3,4 -d ':'", userId);
+    }
+
+    /**
+     * This method reuses `getUserById` because the getent command is the same for
+     * both uid and username.
+     *
+     * @param userName name of user.
+     * @return Shell command string that will read a single user.
+     */
+    public String getUserByName(String userName) {
+        return getUserById(userName);
+    }
+
+    /**
+     * This method supports gid or group name because getent does.
+     *
+     * @param groupId name of group.
+     * @return Shell command string that will read a single group.
+     */
+    public String getGroupById(String groupId) {
+        return String.format("getent group %s | cut -f 1,3,4 -d ':'", groupId);
+    }
+
+    /**
+     * This gives exit code 0 on all tested distributions.
+     *
+     * @return Shell command string that will exit normally (0) on a suitable system.
+     */
+    public String getSystemCheck() {
+        return "getent --version";
+    }
+}
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/OsxShellCommands.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/OsxShellCommands.java
new file mode 100644
index 0000000..0591662
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/OsxShellCommands.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.shell;
+
+/**
+ * Provides shell commands to read users and groups on Mac OSX systems.
+ *
+ * See `man dscl` for more info.
+ */
+class OsxShellCommands implements ShellCommandsProvider {
+    /**
+     * @return Shell command string that will return a list of users.
+     */
+    public String getUsersList() {
+        return "dscl . -readall /Users UniqueID PrimaryGroupID | awk 'BEGIN { OFS = \":\"; ORS=\"\\n\"; i=0;} /RecordName: / {name = $2;i = 0;}" +
+                "/PrimaryGroupID: / {gid = $2;} /^ / {if (i == 0) { i++; name = $1;}} /UniqueID: / {uid = $2;print name, uid, gid;}' | grep -v ^_";
+    }
+
+    /**
+     * @return Shell command string that will return a list of groups.
+     */
+    public String getGroupsList() {
+        return "dscl . -list /Groups PrimaryGroupID  | grep -v '^_' | sed 's/ \\{1,\\}/:/g'";
+    }
+
+    /**
+     *
+     * @param groupName name of group.
+     * @return Shell command string that will return a list of users for a group.
+     */
+    public String getGroupMembers(String groupName) {
+        return String.format("dscl . -read /Groups/%s GroupMembership | cut -f 2- -d ' ' | sed 's/\\ /,/g'", groupName);
+    }
+
+    /**
+     * @param userId name of user.
+     * @return Shell command string that will read a single user.
+     */
+    @Override
+    public String getUserById(String userId) {
+        return String.format("id -P %s | cut -f 1,3,4 -d ':'", userId);
+    }
+
+    /**
+     * @param userName name of user.
+     * @return Shell command string that will read a single user.
+     */
+    public String getUserByName(String userName) {
+        return getUserById(userName); // 'id' command works for both uid/username
+    }
+
+    /**
+     * @param groupId name of group.
+     * @return Shell command string that will read a single group.
+     */
+    public String getGroupById(String groupId) {
+        return String.format(" dscl . -read /Groups/`dscl . -search /Groups gid %s | head -n 1 | cut -f 1` RecordName PrimaryGroupID | awk 'BEGIN { OFS = \":\"; ORS=\"\\n\"; i=0;} " +
+                "/RecordName: / {name = $2;i = 1;}/PrimaryGroupID: / {gid = $2;}; {if (i==1) {print name,gid,\"\"}}'", groupId);
+    }
+
+    /**
+     * @return Shell command string that will exit normally (0) on a suitable system.
+     */
+    public String getSystemCheck() {
+        return "which dscl";
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/RemoteShellCommands.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/RemoteShellCommands.java
new file mode 100644
index 0000000..f622409
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/RemoteShellCommands.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.shell;
+
+class RemoteShellCommands implements ShellCommandsProvider {
+    // Carefully crafted command replacement string:
+    private final static String remoteCommand = "ssh " +
+            "-o 'StrictHostKeyChecking no' " +
+            "-o 'PasswordAuthentication no' " +
+            "-o \"RemoteCommand %s\" " +
+            "-i %s -p %s -l root %s";
+
+    private ShellCommandsProvider innerProvider;
+    private String privateKeyPath;
+    private String remoteHost;
+    private Integer remotePort;
+
+    private RemoteShellCommands() {
+    }
+
+    public static ShellCommandsProvider wrapOtherProvider(ShellCommandsProvider otherProvider, String keyPath, String host, Integer port) {
+        RemoteShellCommands remote = new RemoteShellCommands();
+
+        remote.innerProvider = otherProvider;
+        remote.privateKeyPath = keyPath;
+        remote.remoteHost = host;
+        remote.remotePort = port;
+
+        return remote;
+    }
+
+    public String getUsersList() {
+        return String.format(remoteCommand, innerProvider.getUsersList(), privateKeyPath, remotePort, remoteHost);
+    }
+
+    public String getGroupsList() {
+        return String.format(remoteCommand, innerProvider.getGroupsList(), privateKeyPath, remotePort, remoteHost);
+    }
+
+    public String getGroupMembers(String groupName) {
+        return String.format(remoteCommand, innerProvider.getGroupMembers(groupName), privateKeyPath, remotePort, remoteHost);
+    }
+
+    public String getUserById(String userId) {
+        return String.format(remoteCommand, innerProvider.getUserById(userId), privateKeyPath, remotePort, remoteHost);
+    }
+
+    public String getUserByName(String userName) {
+        return String.format(remoteCommand, innerProvider.getUserByName(userName), privateKeyPath, remotePort, remoteHost);
+    }
+
+    public String getGroupById(String groupId) {
+        return String.format(remoteCommand, innerProvider.getGroupById(groupId), privateKeyPath, remotePort, remoteHost);
+    }
+
+    public String getSystemCheck() {
+        return String.format(remoteCommand, innerProvider.getSystemCheck(), privateKeyPath, remotePort, remoteHost);
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellCommandsProvider.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellCommandsProvider.java
new file mode 100644
index 0000000..ce3e6a4
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellCommandsProvider.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.shell;
+
+/**
+ * Common interface for shell command strings to read users and groups.
+ *
+ */
+interface ShellCommandsProvider {
+    /**
+     * Gets the command for listing users.
+     *
+     * When executed, this command should output one record per line in this format:
+     *
+     * `username:user-id:primary-group-id`
+     *
+     * @return Shell command string that will return a list of users.
+     */
+    String getUsersList();
+
+    /**
+     * Gets the command for listing groups.
+     *
+     * When executed, this command should output one record per line in this format:
+     *
+     * `group-name:group-id`
+     *
+     * @return Shell command string that will return a list of groups.
+     */
+    String getGroupsList();
+
+    /**
+     * Gets the command for listing the members of a group.
+     *
+     * When executed, this command should output one line in this format:
+     *
+     * `user-name-1,user-name-2,user-name-n`
+     *
+     * @param groupName name of group.
+     * @return Shell command string that will return a list of users for a group.
+     */
+    String getGroupMembers(String groupName);
+
+    /**
+     * Gets the command for reading a single user by id.  Implementations may return null if reading a single
+     * user by id is not supported.
+     *
+     * When executed, this command should output a single line, in the format used by `getUsersList`.
+     *
+     * @param userId name of user.
+     * @return Shell command string that will read a single user.
+     */
+    String getUserById(String userId);
+
+    /**
+     * Gets the command for reading a single user.  Implementations may return null if reading a single user by
+     * username is not supported.
+     *
+     * When executed, this command should output a single line, in the format used by `getUsersList`.
+     *
+     * @param userName name of user.
+     * @return Shell command string that will read a single user.
+     */
+    String getUserByName(String userName);
+
+    /**
+     * Gets the command for reading a single group.  Implementations may return null if reading a single group
+     * by name is not supported.
+     *
+     * When executed, this command should output a single line, in the format used by `getGroupsList`.
+     *
+     * @param groupId name of group.
+     * @return Shell command string that will read a single group.
+     */
+    String getGroupById(String groupId);
+
+    /**
+     * Gets the command for checking the suitability of the host system.
+     *
+     * The command is expected to exit with status 0 (zero) to indicate success, and any other status
+     * to indicate failure.
+     *
+     * @return Shell command string that will exit normally (0) on a suitable system.
+     */
+    String getSystemCheck();
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellRunner.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellRunner.java
new file mode 100644
index 0000000..ee7ef41
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellRunner.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.shell;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+public class ShellRunner {
+    private final static Logger logger = LoggerFactory.getLogger(ShellRunner.class);
+
+    static String SHELL = "sh";
+    static String OPTS = "-c";
+    static Integer TIMEOUT = 60;
+
+    public static List<String> runShell(String command) throws IOException {
+        return runShell(command, "<unknown>");
+    }
+
+    public static List<String> runShell(String command, String description) throws IOException {
+        final ProcessBuilder builder = new ProcessBuilder(SHELL, OPTS, command);
+        final List<String> builderCommand = builder.command();
+
+        logger.debug("Run Command '" + description + "': " + builderCommand);
+        final Process proc = builder.start();
+
+        boolean completed;
+        try {
+            completed = proc.waitFor(TIMEOUT, TimeUnit.SECONDS);
+        } catch (InterruptedException irexc) {
+            throw new IOException(irexc.getMessage(), irexc.getCause());
+        }
+
+        if (!completed) {
+            throw new IllegalStateException("Shell command '" + command + "' did not complete during the allotted time period");
+        }
+
+        if (proc.exitValue() != 0) {
+            try (final Reader stderr = new InputStreamReader(proc.getErrorStream());
+                 final BufferedReader reader = new BufferedReader(stderr)) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    logger.warn(line.trim());
+                }
+            }
+            throw new IOException("Command exit non-zero: " + proc.exitValue());
+        }
+
+        final List<String> lines = new ArrayList<>();
+        try (final Reader stdin = new InputStreamReader(proc.getInputStream());
+             final BufferedReader reader = new BufferedReader(stdin)) {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                lines.add(line.trim());
+            }
+        }
+
+        return lines;
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellUserGroupProvider.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellUserGroupProvider.java
new file mode 100644
index 0000000..1d709ac
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/shell/ShellUserGroupProvider.java
@@ -0,0 +1,678 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+package org.apache.nifi.registry.security.authorization.shell;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext;
+import org.apache.nifi.registry.security.authorization.Group;
+import org.apache.nifi.registry.security.authorization.User;
+import org.apache.nifi.registry.security.authorization.UserAndGroups;
+import org.apache.nifi.registry.security.authorization.UserGroupProvider;
+import org.apache.nifi.registry.security.authorization.UserGroupProviderInitializationContext;
+import org.apache.nifi.registry.security.authorization.exception.AuthorizationAccessException;
+import org.apache.nifi.registry.security.exception.SecurityProviderCreationException;
+import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException;
+import org.apache.nifi.registry.util.FormatUtils;
+import org.apache.nifi.registry.util.PropertyValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/*
+ * ShellUserGroupProvider implements UserGroupProvider by way of shell commands.
+ */
+public class ShellUserGroupProvider implements UserGroupProvider {
+    private final static Logger logger = LoggerFactory.getLogger(ShellUserGroupProvider.class);
+
+    private final static String OS_TYPE_ERROR = "Unsupported operating system.";
+    private final static String SYS_CHECK_ERROR = "System check failed - cannot provide users and groups.";
+    private final static Map<String, User> usersById = new HashMap<>();   // id == identifier
+    private final static Map<String, User> usersByName = new HashMap<>(); // name == identity
+    private final static Map<String, Group> groupsById = new HashMap<>();
+
+    public static final String REFRESH_DELAY_PROPERTY = "Refresh Delay";
+    private static final long MINIMUM_SYNC_INTERVAL_MILLISECONDS = 10_000;
+
+    public static final String EXCLUDE_USER_PROPERTY = "Exclude Users";
+    public static final String EXCLUDE_GROUP_PROPERTY = "Exclude Groups";
+
+    private long fixedDelay;
+    private Pattern excludeUsers;
+    private Pattern excludeGroups;
+
+    // Our scheduler has one thread for users, one for groups:
+    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
+
+    // Our shell timeout, in seconds:
+    @SuppressWarnings("FieldCanBeLocal")
+    private final Integer shellTimeout = 10;
+
+    // Commands selected during initialization:
+    private ShellCommandsProvider selectedShellCommands;
+
+    // Start of the UserGroupProvider implementation.  Javadoc strings
+    // copied from the interface definition for reference.
+
+    /**
+     * Retrieves all users. Must be non null
+     *
+     * @return a list of users
+     * @throws AuthorizationAccessException if there was an unexpected error performing the operation
+     */
+    @Override
+    public Set<User> getUsers() throws AuthorizationAccessException {
+        synchronized (usersById) {
+            logger.debug("getUsers has user set of size: " + usersById.size());
+            return new HashSet<>(usersById.values());
+        }
+    }
+
+    /**
+     * Retrieves the user with the given identifier.
+     *
+     * @param identifier the id of the user to retrieve
+     * @return the user with the given id, or null if no matching user was found
+     * @throws AuthorizationAccessException if there was an unexpected error performing the operation
+     */
+    @Override
+    public User getUser(String identifier) throws AuthorizationAccessException {
+        User user;
+
+        synchronized (usersById) {
+            user = usersById.get(identifier);
+        }
+
+        if (user == null) {
+            logger.debug("getUser (by id) user not found: " + identifier);
+        } else {
+            logger.debug("getUser (by id) found user: " + user + " for id: " + identifier);
+        }
+        return user;
+    }
+
+    /**
+     * Retrieves the user with the given identity.
+     *
+     * @param identity the identity of the user to retrieve
+     * @return the user with the given identity, or null if no matching user was found
+     * @throws AuthorizationAccessException if there was an unexpected error performing the operation
+     */
+    @Override
+    public User getUserByIdentity(String identity) throws AuthorizationAccessException {
+        User user;
+
+        synchronized (usersByName) {
+            user = usersByName.get(identity);
+        }
+
+        if (user == null) {
+            refreshOneUser(selectedShellCommands.getUserByName(identity), "Get Single User by Name");
+            user = usersByName.get(identity);
+        }
+
+        if (user == null) {
+            logger.debug("getUser (by name) user not found: " + identity);
+        } else {
+            logger.debug("getUser (by name) found user: " + user.getIdentity() + " for name: " + identity);
+        }
+        return user;
+    }
+
+    /**
+     * Retrieves all groups. Must be non null
+     *
+     * @return a list of groups
+     * @throws AuthorizationAccessException if there was an unexpected error performing the operation
+     */
+    @Override
+    public Set<Group> getGroups() throws AuthorizationAccessException {
+        synchronized (groupsById) {
+            logger.debug("getGroups has group set of size: " + groupsById.size());
+            return new HashSet<>(groupsById.values());
+        }
+    }
+
+    /**
+     * Retrieves a Group by Id.
+     *
+     * @param identifier the identifier of the Group to retrieve
+     * @return the Group with the given identifier, or null if no matching group was found
+     * @throws AuthorizationAccessException if there was an unexpected error performing the operation
+     */
+    @Override
+    public Group getGroup(String identifier) throws AuthorizationAccessException {
+        Group group;
+
+        synchronized (groupsById) {
+            group = groupsById.get(identifier);
+        }
+
+        if (group == null) {
+            refreshOneGroup(selectedShellCommands.getGroupById(identifier), "Get Single Group by Id");
+            group = groupsById.get(identifier);
+        }
+
+        if (group == null) {
+            logger.debug("getGroup (by id) group not found: " + identifier);
+        } else {
+            logger.debug("getGroup (by id) found group: " + group.getName() + " for id: " + identifier);
+        }
+        return group;
+
+    }
+
+    /**
+     * Gets a user and their groups.
+     *
+     * @return the UserAndGroups for the specified identity
+     * @throws AuthorizationAccessException if there was an unexpected error performing the operation
+     */
+    @Override
+    public UserAndGroups getUserAndGroups(String identity) throws AuthorizationAccessException {
+        User user = getUserByIdentity(identity);
+        logger.debug("Retrieved user {} for identity {}", new Object[]{user, identity});
+
+        Set<Group> groups = new HashSet<>();
+        if (user != null) {
+            for (Group g : getGroups()) {
+                if (g.getUsers().contains(user.getIdentifier())) {
+                    logger.debug("User {} belongs to group {}", new Object[]{user.getIdentity(), g.getName()});
+                    groups.add(g);
+                }
+            }
+        }
+
+        if (groups.isEmpty()) {
+            logger.debug("User {} belongs to no groups", user);
+        }
+
+        return new UserAndGroups() {
+            @Override
+            public User getUser() {
+                return user;
+            }
+
+            @Override
+            public Set<Group> getGroups() {
+                return groups;
+            }
+        };
+    }
+
+    /**
+     * Called immediately after instance creation for implementers to perform additional setup
+     *
+     * @param initializationContext in which to initialize
+     */
+    @Override
+    public void initialize(UserGroupProviderInitializationContext initializationContext) throws SecurityProviderCreationException {
+    }
+
+    /**
+     * Called to configure the Authorizer.
+     *
+     * @param configurationContext at the time of configuration
+     * @throws SecurityProviderCreationException for any issues configuring the provider
+     */
+    @Override
+    public void onConfigured(AuthorizerConfigurationContext configurationContext) throws SecurityProviderCreationException {
+        fixedDelay = getDelayProperty(configurationContext, REFRESH_DELAY_PROPERTY, "5 mins");
+
+        // Our next init step is to select the command set based on the operating system name:
+        ShellCommandsProvider commands = getCommandsProvider();
+
+        if (commands == null) {
+            commands = getCommandsProviderFromName(null);
+            setCommandsProvider(commands);
+        }
+
+        // Our next init step is to run the system check from that command set to determine if the other commands
+        // will work on this host or not.
+        try {
+            ShellRunner.runShell(commands.getSystemCheck());
+        } catch (final Exception e) {
+            logger.error("initialize exception: " + e + " system check command: " + commands.getSystemCheck());
+            throw new SecurityProviderCreationException(SYS_CHECK_ERROR, e);
+        }
+
+        // The next step is to add the user and group exclude regexes:
+        try {
+            excludeGroups = Pattern.compile(getProperty(configurationContext, EXCLUDE_GROUP_PROPERTY, ""));
+            excludeUsers = Pattern.compile(getProperty(configurationContext, EXCLUDE_USER_PROPERTY, ""));
+        } catch (final PatternSyntaxException e) {
+            throw new SecurityProviderCreationException(e);
+        }
+
+        // With our command set selected, and our system check passed, we can pull in the users and groups:
+        refreshUsersAndGroups();
+
+        // And finally, our last init step is to fire off the refresh thread:
+        scheduler.scheduleWithFixedDelay(() -> {
+            try {
+                refreshUsersAndGroups();
+            }catch (final Throwable t) {
+                logger.error("", t);
+            }
+        }, fixedDelay, fixedDelay, TimeUnit.MILLISECONDS);
+
+    }
+
+    private static ShellCommandsProvider getCommandsProviderFromName(String osName) {
+        if (osName == null) {
+            osName = System.getProperty("os.name");
+        }
+
+        ShellCommandsProvider commands;
+        if (osName.startsWith("Linux")) {
+            logger.debug("Selected Linux command set.");
+            commands = new NssShellCommands();
+        } else if (osName.startsWith("Mac OS X")) {
+            logger.debug("Selected OSX command set.");
+            commands = new OsxShellCommands();
+        } else {
+            throw new SecurityProviderCreationException(OS_TYPE_ERROR);
+        }
+        return commands;
+    }
+
+    private String getProperty(AuthorizerConfigurationContext authContext, String propertyName, String defaultValue) {
+        final PropertyValue property = authContext.getProperty(propertyName);
+        final String value;
+
+        if (property != null && property.isSet()) {
+            value = property.getValue();
+        } else {
+            value = defaultValue;
+        }
+        return value;
+
+    }
+
+    private long getDelayProperty(AuthorizerConfigurationContext authContext, String propertyName, String defaultValue) {
+        final PropertyValue intervalProperty = authContext.getProperty(propertyName);
+        final String propertyValue;
+        final long syncInterval;
+
+        if (intervalProperty.isSet()) {
+            propertyValue = intervalProperty.getValue();
+        } else {
+            propertyValue = defaultValue;
+        }
+
+        try {
+            syncInterval = Math.round(FormatUtils.getPreciseTimeDuration(propertyValue, TimeUnit.MILLISECONDS));
+        } catch (final IllegalArgumentException ignored) {
+            throw new SecurityProviderCreationException(String.format("The %s '%s' is not a valid time interval.", propertyName, propertyValue));
+        }
+
+        if (syncInterval < MINIMUM_SYNC_INTERVAL_MILLISECONDS) {
+            throw new SecurityProviderCreationException(String.format("The %s '%s' is below the minimum value of '%d ms'", propertyName, propertyValue, MINIMUM_SYNC_INTERVAL_MILLISECONDS));
+        }
+        return syncInterval;
+    }
+
+    /**
+     * Called immediately before instance destruction for implementers to release resources.
+     *
+     * @throws SecurityProviderDestructionException If pre-destruction fails.
+     */
+    @Override
+    public void preDestruction() throws SecurityProviderDestructionException {
+        try {
+            scheduler.shutdownNow();
+        } catch (final Exception ignored) {
+        }
+    }
+
+    public ShellCommandsProvider getCommandsProvider() {
+        return selectedShellCommands;
+    }
+
+    public void setCommandsProvider(ShellCommandsProvider commandsProvider) {
+        selectedShellCommands = commandsProvider;
+    }
+
+    /**
+     * Refresh a single user.
+     *
+     * @param command     Shell command to read a single user.  Pre-formatted by caller.
+     * @param description Shell command description.
+     */
+    private void refreshOneUser(String command, String description) {
+        if (command != null) {
+            Map<String, User> idToUser = new HashMap<>();
+            Map<String, User> usernameToUser = new HashMap<>();
+            Map<String, User> gidToUser = new HashMap<>();
+            List<String> userLines;
+
+            try {
+                userLines = ShellRunner.runShell(command, description);
+                rebuildUsers(userLines, idToUser, usernameToUser, gidToUser);
+            } catch (final IOException ioexc) {
+                logger.error("refreshOneUser shell exception: " + ioexc);
+            }
+
+            if (idToUser.size() > 0) {
+                synchronized (usersById) {
+                    usersById.putAll(idToUser);
+                }
+            }
+
+            if (usernameToUser.size() > 0) {
+                synchronized (usersByName) {
+                    usersByName.putAll(usernameToUser);
+                }
+            }
+        } else {
+            logger.info("Get Single User not supported on this system.");
+        }
+    }
+
+    /**
+     * Refresh a single group.
+     *
+     * @param command     Shell command to read a single group.  Pre-formatted by caller.
+     * @param description Shell command description.
+     */
+    private void refreshOneGroup(String command, String description) {
+        if (command != null) {
+            Map<String, Group> gidToGroup = new HashMap<>();
+            List<String> groupLines;
+
+            try {
+                groupLines = ShellRunner.runShell(command, description);
+                rebuildGroups(groupLines, gidToGroup);
+            } catch (final IOException ioexc) {
+                logger.error("refreshOneGroup shell exception: " + ioexc);
+            }
+
+            if (gidToGroup.size() > 0) {
+                synchronized (groupsById) {
+                    groupsById.putAll(gidToGroup);
+                }
+            }
+        } else {
+            logger.info("Get Single Group not supported on this system.");
+        }
+    }
+
+    /**
+     * This is our entry point for user and group refresh.  This method runs the top-level
+     * `getUserList()` and `getGroupsList()` shell commands, then passes those results to the
+     * other methods for record parse, extract, and object construction.
+     */
+    private void refreshUsersAndGroups() {
+        Map<String, User> uidToUser = new HashMap<>();
+        Map<String, User> usernameToUser = new HashMap<>();
+        Map<String, User> gidToUser = new HashMap<>();
+        Map<String, Group> gidToGroup = new HashMap<>();
+
+        List<String> userLines;
+        List<String> groupLines;
+
+        try {
+            userLines = ShellRunner.runShell(selectedShellCommands.getUsersList(), "Get Users List");
+            groupLines = ShellRunner.runShell(selectedShellCommands.getGroupsList(), "Get Groups List");
+        } catch (final IOException ioexc) {
+            logger.error("refreshUsersAndGroups shell exception: " + ioexc);
+            return;
+        }
+
+        rebuildUsers(userLines, uidToUser, usernameToUser, gidToUser);
+        rebuildGroups(groupLines, gidToGroup);
+        reconcilePrimaryGroups(gidToUser, gidToGroup);
+
+        synchronized (usersById) {
+            usersById.clear();
+            usersById.putAll(uidToUser);
+
+            if (logger.isTraceEnabled()) {
+                logger.trace("=== Users by id...");
+                Set<User> sortedUsers = new TreeSet<>(Comparator.comparing(User::getIdentity));
+                sortedUsers.addAll(usersById.values());
+                sortedUsers.forEach(u -> logger.trace("=== " + u.toString()));
+            }
+        }
+
+        synchronized (usersByName) {
+            usersByName.clear();
+            usersByName.putAll(usernameToUser);
+            logger.debug("users now size: " + usersByName.size());
+        }
+
+        synchronized (groupsById) {
+            groupsById.clear();
+            groupsById.putAll(gidToGroup);
+            logger.debug("groups now size: " + groupsById.size());
+
+            if (logger.isTraceEnabled()) {
+                logger.trace("=== Groups by id...");
+                Set<Group> sortedGroups = new TreeSet<>(Comparator.comparing(Group::getName));
+                sortedGroups.addAll(groupsById.values());
+                sortedGroups.forEach(g -> logger.trace("=== " + g.toString()));
+            }
+        }
+    }
+
+    /**
+     * This method parses the output of the `getUsersList()` shell command, where we expect the output
+     * to look like `user-name:user-id:primary-group-id`.
+     * <p>
+     * This method splits each output line on the ":" and attempts to build a User object
+     * from the resulting name, uid, and primary gid.  Unusable records are logged.
+     */
+    private void rebuildUsers(List<String> userLines, Map<String, User> idToUser, Map<String, User> usernameToUser, Map<String, User> gidToUser) {
+        userLines.forEach(line -> {
+            logger.trace("Processing user: {}", new Object[]{line});
+
+            String[] record = line.split(":");
+            if (record.length > 2) {
+                String userIdentity = record[0], userIdentifier = record[1], primaryGroupIdentifier = record[2];
+
+                if (!StringUtils.isBlank(userIdentifier) && !StringUtils.isBlank(userIdentity) && !excludeUsers.matcher(userIdentity).matches()) {
+                    User user = new User.Builder()
+                            .identity(userIdentity)
+                            .identifierGenerateFromSeed(getUserIdentifierSeed(userIdentity))
+                            .build();
+                    idToUser.put(user.getIdentifier(), user);
+                    usernameToUser.put(userIdentity, user);
+                    logger.debug("Refreshed user {}", new Object[]{user});
+
+                    if (!StringUtils.isBlank(primaryGroupIdentifier)) {
+                        // create a temporary group to deterministically generate the group id and associate this user
+                        Group group = new Group.Builder()
+                                .name(primaryGroupIdentifier)
+                                .identifierGenerateFromSeed(getGroupIdentifierSeed(primaryGroupIdentifier))
+                                .build();
+                        gidToUser.put(group.getIdentifier(), user);
+                        logger.debug("Associated primary group {} with user {}", new Object[]{group.getIdentifier(), userIdentity});
+                    } else {
+                        logger.warn("Null or empty primary group id for: " + userIdentity);
+                    }
+
+                } else {
+                    logger.warn("Null, empty, or skipped user name: " + userIdentity + " or id: " + userIdentifier);
+                }
+            } else {
+                logger.warn("Unexpected record format.  Expected 3 or more colon separated values per line.");
+            }
+        });
+    }
+
+    /**
+     * This method parses the output of the `getGroupsList()` shell command, where we expect the output
+     * to look like `group-name:group-id`.
+     * <p>
+     * This method splits each output line on the ":" and attempts to build a Group object
+     * from the resulting name and gid.  Unusable records are logged.
+     * <p>
+     * This command also runs the `getGroupMembers(username)` command once per group.  The expected output
+     * of that command should look like `group-name-1,group-name-2`.
+     */
+    private void rebuildGroups(List<String> groupLines, Map<String, Group> groupsById) {
+        groupLines.forEach(line -> {
+            logger.trace("Processing group: {}", new Object[]{line});
+
+            String[] record = line.split(":");
+            if (record.length > 1) {
+                Set<String> users = new HashSet<>();
+                String groupName = record[0], groupIdentifier = record[1];
+
+                try {
+                    String groupMembersCommand = selectedShellCommands.getGroupMembers(groupName);
+                    List<String> memberLines = ShellRunner.runShell(groupMembersCommand);
+                    // Use the first line only, and log if the line count isn't exactly one:
+                    if (!memberLines.isEmpty()) {
+                        String memberLine = memberLines.get(0);
+                        if (!StringUtils.isBlank(memberLine)) {
+                            String[] members = memberLine.split(",");
+                            for (String userIdentity : members) {
+                                if (!StringUtils.isBlank(userIdentity)) {
+                                    User tempUser = new User.Builder()
+                                            .identity(userIdentity)
+                                            .identifierGenerateFromSeed(getUserIdentifierSeed(userIdentity))
+                                            .build();
+                                    users.add(tempUser.getIdentifier());
+                                    logger.debug("Added temp user {} for group {}", new Object[]{tempUser, groupName});
+                                }
+                            }
+                        } else {
+                            logger.debug("list membership returned no members");
+                        }
+                    } else {
+                        logger.debug("list membership returned zero lines.");
+                    }
+                    if (memberLines.size() > 1) {
+                        logger.error("list membership returned too many lines, only used the first.");
+                    }
+
+                } catch (final IOException ioexc) {
+                    logger.error("list membership shell exception: " + ioexc);
+                }
+
+                if (!StringUtils.isBlank(groupIdentifier) && !StringUtils.isBlank(groupName) && !excludeGroups.matcher(groupName).matches()) {
+                    Group group = new Group.Builder()
+                            .name(groupName)
+                            .identifierGenerateFromSeed(getGroupIdentifierSeed(groupIdentifier))
+                            .addUsers(users)
+                            .build();
+                    groupsById.put(group.getIdentifier(), group);
+                    logger.debug("Refreshed group {}", new Object[] {group});
+                } else {
+                    logger.warn("Null, empty, or skipped group name: " + groupName + " or id: " + groupIdentifier);
+                }
+            } else {
+                logger.warn("Unexpected record format.  Expected 1 or more comma separated values.");
+            }
+        });
+    }
+
+    /**
+     * This method parses the output of the `getGroupsList()` shell command, where we expect the output
+     * to look like `group-name:group-id`.
+     * <p>
+     * This method splits each output line on the ":" and attempts to build a Group object
+     * from the resulting name and gid.
+     */
+    private void reconcilePrimaryGroups(Map<String, User> uidToUser, Map<String, Group> gidToGroup) {
+        uidToUser.forEach((primaryGid, primaryUser) -> {
+            Group primaryGroup = gidToGroup.get(primaryGid);
+
+            if (primaryGroup == null) {
+                logger.warn("Primary group {} not found for {}", new Object[]{primaryGid, primaryUser.getIdentity()});
+            } else if (!excludeGroups.matcher(primaryGroup.getName()).matches()) {
+                Set<String> groupUsers = primaryGroup.getUsers();
+                if (!groupUsers.contains(primaryUser.getIdentifier())) {
+                    Set<String> updatedUserIdentifiers = new HashSet<>(groupUsers);
+                    updatedUserIdentifiers.add(primaryUser.getIdentifier());
+
+                    Group updatedGroup = new Group.Builder()
+                            .identifier(primaryGroup.getIdentifier())
+                            .name(primaryGroup.getName())
+                            .addUsers(updatedUserIdentifiers)
+                            .build();
+                    gidToGroup.put(updatedGroup.getIdentifier(), updatedGroup);
+                    logger.debug("Added user {} to primary group {}", new Object[]{primaryUser, updatedGroup});
+                } else {
+                    logger.debug("Primary group {} already contains user {}", new Object[]{primaryGroup, primaryUser});
+                }
+            } else {
+                logger.debug("Primary group {} excluded from matcher for {}", new Object[]{primaryGroup.getName(), primaryUser.getIdentity()});
+            }
+        });
+    }
+
+    private String getUserIdentifierSeed(final String userIdentifier) {
+        return userIdentifier + "-user";
+    }
+
+    private String getGroupIdentifierSeed(final String groupIdentifier) {
+        return groupIdentifier + "-group";
+    }
+
+
+    /**
+     * @return The fixed refresh delay.
+     */
+    public long getRefreshDelay() {
+        return fixedDelay;
+    }
+
+    /**
+     * Testing concession for clearing the internal caches.
+     */
+    void clearCaches() {
+        synchronized (usersById) {
+            usersById.clear();
+        }
+
+        synchronized (usersByName) {
+            usersByName.clear();
+        }
+
+        synchronized (groupsById) {
+            groupsById.clear();
+        }
+    }
+
+    /**
+     * @return The size of the internal user cache.
+     */
+    public int userCacheSize() {
+        return usersById.size();
+    }
+
+    /**
+     * @return The size of the internal group cache.
+     */
+    public int groupCacheSize() {
+        return groupsById.size();
+    }
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/resources/META-INF/services/org.apache.nifi.registry.security.authorization.UserGroupProvider b/nifi-registry-core/nifi-registry-framework/src/main/resources/META-INF/services/org.apache.nifi.registry.security.authorization.UserGroupProvider
index ee28c07..a4ac129 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/resources/META-INF/services/org.apache.nifi.registry.security.authorization.UserGroupProvider
+++ b/nifi-registry-core/nifi-registry-framework/src/main/resources/META-INF/services/org.apache.nifi.registry.security.authorization.UserGroupProvider
@@ -15,4 +15,5 @@
 org.apache.nifi.registry.security.authorization.CompositeUserGroupProvider
 org.apache.nifi.registry.security.authorization.CompositeConfigurableUserGroupProvider
 org.apache.nifi.registry.security.authorization.file.FileUserGroupProvider
-org.apache.nifi.registry.security.ldap.tenants.LdapUserGroupProvider
\ No newline at end of file
+org.apache.nifi.registry.security.ldap.tenants.LdapUserGroupProvider
+org.apache.nifi.registry.security.authorization.shell.ShellUserGroupProvider
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
index 9f63754..38a6ee8 100644
--- a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
@@ -166,6 +166,25 @@
     To enable the ldap-user-group-provider remove 2 lines. This is 2 of 2. -->
 
     <!--
+        The ShellUserGroupProvider provides support for retrieving users and groups by way of shell commands
+        on systems that support `sh`.  Implementations available for Linux and Mac OS, and are selected by the
+        provider based on the system property `os.name`.
+
+        'Refresh Delay' - duration to wait between subsequent refreshes.  Default is '5 mins'.
+        'Exclude Groups' - regular expression used to exclude groups.  Default is '', which means no groups are excluded.
+        'Exclude Users' - regular expression used to exclude users.  Default is '', which means no users are excluded.
+    -->
+    <!-- To enable the shell-user-group-provider remove 2 lines. This is 1 of 2.
+    <userGroupProvider>
+        <identifier>shell-user-group-provider</identifier>
+        <class>org.apache.nifi.registry.security.authorization.shell.ShellUserGroupProvider</class>
+        <property name="Refresh Delay">5 mins</property>
+        <property name="Exclude Groups"></property>
+        <property name="Exclude Users"></property>
+    </userGroupProvider>
+    To enable the shell-user-group-provider remove 2 lines. This is 2 of 2. -->
+
+    <!--
         The CompositeUserGroupProvider will provide support for retrieving users and groups from multiple sources.
 
         - User Group Provider [unique key] - The identifier of user group providers to load from. The name of
diff --git a/nifi-registry-core/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/FormatUtils.java b/nifi-registry-core/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/FormatUtils.java
index c1e353d..aa207c5 100644
--- a/nifi-registry-core/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/FormatUtils.java
+++ b/nifi-registry-core/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/FormatUtils.java
@@ -17,12 +17,13 @@
 package org.apache.nifi.registry.util;
 
 import java.text.NumberFormat;
+import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 public class FormatUtils {
-
     private static final String UNION = "|";
 
     // for Data Sizes
@@ -41,8 +42,9 @@ public class FormatUtils {
     private static final String WEEKS = join(UNION, "w", "wk", "wks", "week", "weeks");
 
     private static final String VALID_TIME_UNITS = join(UNION, NANOS, MILLIS, SECS, MINS, HOURS, DAYS, WEEKS);
-    public static final String TIME_DURATION_REGEX = "(\\d+)\\s*(" + VALID_TIME_UNITS + ")";
+    public static final String TIME_DURATION_REGEX = "([\\d.]+)\\s*(" + VALID_TIME_UNITS + ")";
     public static final Pattern TIME_DURATION_PATTERN = Pattern.compile(TIME_DURATION_REGEX);
+    private static final List<Long> TIME_UNIT_MULTIPLIERS = Arrays.asList(1000L, 1000L, 1000L, 60L, 60L, 24L);
 
     /**
      * Formats the specified count by adding commas.
@@ -58,7 +60,7 @@ public class FormatUtils {
      * Formats the specified duration in 'mm:ss.SSS' format.
      *
      * @param sourceDuration the duration to format
-     * @param sourceUnit the unit to interpret the duration
+     * @param sourceUnit     the unit to interpret the duration
      * @return representation of the given time data in minutes/seconds
      */
     public static String formatMinutesSeconds(final long sourceDuration, final TimeUnit sourceUnit) {
@@ -79,7 +81,7 @@ public class FormatUtils {
      * Formats the specified duration in 'HH:mm:ss.SSS' format.
      *
      * @param sourceDuration the duration to format
-     * @param sourceUnit the unit to interpret the duration
+     * @param sourceUnit     the unit to interpret the duration
      * @return representation of the given time data in hours/minutes/seconds
      */
     public static String formatHoursMinutesSeconds(final long sourceDuration, final TimeUnit sourceUnit) {
@@ -139,65 +141,230 @@ public class FormatUtils {
         return format.format(dataSize) + " bytes";
     }
 
+    /**
+     * Returns a time duration in the requested {@link TimeUnit} after parsing the {@code String}
+     * input. If the resulting value is a decimal (i.e.
+     * {@code 25 hours -> TimeUnit.DAYS = 1.04}), the value is rounded.
+     *
+     * @param value the raw String input (i.e. "28 minutes")
+     * @param desiredUnit the requested output {@link TimeUnit}
+     * @return the whole number value of this duration in the requested units
+     * @deprecated As of Apache NiFi 1.9.0, because this method only returns whole numbers, use {@link #getPreciseTimeDuration(String, TimeUnit)} when possible.
+     */
+    @Deprecated
     public static long getTimeDuration(final String value, final TimeUnit desiredUnit) {
+        return Math.round(getPreciseTimeDuration(value, desiredUnit));
+    }
+
+    /**
+     * Returns the parsed and converted input in the requested units.
+     * <p>
+     * If the value is {@code 0 <= x < 1} in the provided units, the units will first be converted to a smaller unit to get a value >= 1 (i.e. 0.5 seconds -> 500 milliseconds).
+     * This is because the underlying unit conversion cannot handle decimal values.
+     * <p>
+     * If the value is {@code x >= 1} but x is not a whole number, the units will first be converted to a smaller unit to attempt to get a whole number value (i.e. 1.5 seconds -> 1500 milliseconds).
+     * <p>
+     * If the value is {@code x < 1000} and the units are {@code TimeUnit.NANOSECONDS}, the result will be a whole number of nanoseconds, rounded (i.e. 123.4 ns -> 123 ns).
+     * <p>
+     * This method handles decimal values over {@code 1 ns}, but {@code < 1 ns} will return {@code 0} in any other unit.
+     * <p>
+     * Examples:
+     * <p>
+     * "10 seconds", {@code TimeUnit.MILLISECONDS} -> 10_000.0
+     * "0.010 s", {@code TimeUnit.MILLISECONDS} -> 10.0
+     * "0.010 s", {@code TimeUnit.SECONDS} -> 0.010
+     * "0.010 ns", {@code TimeUnit.NANOSECONDS} -> 1
+     * "0.010 ns", {@code TimeUnit.MICROSECONDS} -> 0
+     *
+     * @param value       the {@code String} input
+     * @param desiredUnit the desired output {@link TimeUnit}
+     * @return the parsed and converted amount (without a unit)
+     */
+    public static double getPreciseTimeDuration(final String value, final TimeUnit desiredUnit) {
         final Matcher matcher = TIME_DURATION_PATTERN.matcher(value.toLowerCase());
         if (!matcher.matches()) {
-            throw new IllegalArgumentException("Value '" + value + "' is not a valid Time Duration");
+            throw new IllegalArgumentException("Value '" + value + "' is not a valid time duration");
         }
 
         final String duration = matcher.group(1);
         final String units = matcher.group(2);
-        TimeUnit specifiedTimeUnit = null;
-        switch (units.toLowerCase()) {
+
+        double durationVal = Double.parseDouble(duration);
+        TimeUnit specifiedTimeUnit;
+
+        // The TimeUnit enum doesn't have a value for WEEKS, so handle this case independently
+        if (isWeek(units)) {
+            specifiedTimeUnit = TimeUnit.DAYS;
+            durationVal *= 7;
+        } else {
+            specifiedTimeUnit = determineTimeUnit(units);
+        }
+
+        // The units are now guaranteed to be in DAYS or smaller
+        long durationLong;
+        if (durationVal == Math.rint(durationVal)) {
+            durationLong = Math.round(durationVal);
+        } else {
+            // Try reducing the size of the units to make the input a long
+            List wholeResults = makeWholeNumberTime(durationVal, specifiedTimeUnit);
+            durationLong = (long) wholeResults.get(0);
+            specifiedTimeUnit = (TimeUnit) wholeResults.get(1);
+        }
+
+        return desiredUnit.convert(durationLong, specifiedTimeUnit);
+    }
+
+    /**
+     * Converts the provided time duration value to one that can be represented as a whole number.
+     * Returns a {@code List} containing the new value as a {@code long} at index 0 and the
+     * {@link TimeUnit} at index 1. If the incoming value is already whole, it is returned as is.
+     * If the incoming value cannot be made whole, a whole approximation is returned. For values
+     * {@code >= 1 TimeUnit.NANOSECONDS}, the value is rounded (i.e. 123.4 ns -> 123 ns).
+     * For values {@code < 1 TimeUnit.NANOSECONDS}, the constant [1L, {@code TimeUnit.NANOSECONDS}] is returned as the smallest measurable unit of time.
+     * <p>
+     * Examples:
+     * <p>
+     * 1, {@code TimeUnit.SECONDS} -> [1, {@code TimeUnit.SECONDS}]
+     * 1.1, {@code TimeUnit.SECONDS} -> [1100, {@code TimeUnit.MILLISECONDS}]
+     * 0.1, {@code TimeUnit.SECONDS} -> [100, {@code TimeUnit.MILLISECONDS}]
+     * 0.1, {@code TimeUnit.NANOSECONDS} -> [1, {@code TimeUnit.NANOSECONDS}]
+     *
+     * @param decimal  the time duration as a decimal
+     * @param timeUnit the current time unit
+     * @return the time duration as a whole number ({@code long}) and the smaller time unit used
+     */
+    protected static List<Object> makeWholeNumberTime(double decimal, TimeUnit timeUnit) {
+        // If the value is already a whole number, return it and the current time unit
+        if (decimal == Math.rint(decimal)) {
+            return Arrays.asList(new Object[]{(long) decimal, timeUnit});
+        } else if (TimeUnit.NANOSECONDS == timeUnit) {
+            // The time unit is as small as possible
+            if (decimal < 1.0) {
+                decimal = 1;
+            } else {
+                decimal = Math.rint(decimal);
+            }
+            return Arrays.asList(new Object[]{(long) decimal, timeUnit});
+        } else {
+            // Determine the next time unit and the respective multiplier
+            TimeUnit smallerTimeUnit = getSmallerTimeUnit(timeUnit);
+            long multiplier = calculateMultiplier(timeUnit, smallerTimeUnit);
+
+            // Recurse with the original number converted to the smaller unit
+            return makeWholeNumberTime(decimal * multiplier, smallerTimeUnit);
+        }
+    }
+
+    /**
+     * Returns the numerical multiplier to convert a value from {@code originalTimeUnit} to
+     * {@code newTimeUnit} (i.e. for {@code TimeUnit.DAYS -> TimeUnit.MINUTES} would return
+     * 24 * 60 = 1440). If the original and new units are the same, returns 1. If the new unit
+     * is larger than the original (i.e. the result would be less than 1), throws an
+     * {@link IllegalArgumentException}.
+     *
+     * @param originalTimeUnit the source time unit
+     * @param newTimeUnit      the destination time unit
+     * @return the numerical multiplier between the units
+     */
+    protected static long calculateMultiplier(TimeUnit originalTimeUnit, TimeUnit newTimeUnit) {
+        if (originalTimeUnit == newTimeUnit) {
+            return 1;
+        } else if (originalTimeUnit.ordinal() < newTimeUnit.ordinal()) {
+            throw new IllegalArgumentException("The original time unit '" + originalTimeUnit + "' must be larger than the new time unit '" + newTimeUnit + "'");
+        } else {
+            int originalOrd = originalTimeUnit.ordinal();
+            int newOrd = newTimeUnit.ordinal();
+
+            List<Long> unitMultipliers = TIME_UNIT_MULTIPLIERS.subList(newOrd, originalOrd);
+            return unitMultipliers.stream().reduce(1L, (a, b) -> (long) a * b);
+        }
+    }
+
+    /**
+     * Returns the next smallest {@link TimeUnit} (i.e. {@code TimeUnit.DAYS -> TimeUnit.HOURS}).
+     * If the parameter is {@code null} or {@code TimeUnit.NANOSECONDS}, an
+     * {@link IllegalArgumentException} is thrown because there is no valid smaller TimeUnit.
+     *
+     * @param originalUnit the TimeUnit
+     * @return the next smaller TimeUnit
+     */
+    protected static TimeUnit getSmallerTimeUnit(TimeUnit originalUnit) {
+        if (originalUnit == null || TimeUnit.NANOSECONDS == originalUnit) {
+            throw new IllegalArgumentException("Cannot determine a smaller time unit than '" + originalUnit + "'");
+        } else {
+            return TimeUnit.values()[originalUnit.ordinal() - 1];
+        }
+    }
+
+    /**
+     * Returns {@code true} if this raw unit {@code String} is parsed as representing "weeks", which does not have a value in the {@link TimeUnit} enum.
+     *
+     * @param rawUnit the String containing the desired unit
+     * @return true if the unit is "weeks"; false otherwise
+     */
+    protected static boolean isWeek(final String rawUnit) {
+        switch (rawUnit) {
+            case "w":
+            case "wk":
+            case "wks":
+            case "week":
+            case "weeks":
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Returns the {@link TimeUnit} enum that maps to the provided raw {@code String} input. The
+     * highest time unit is {@code TimeUnit.DAYS}. Any input that cannot be parsed will result in
+     * an {@link IllegalArgumentException}.
+     *
+     * @param rawUnit the String to parse
+     * @return the TimeUnit
+     */
+    protected static TimeUnit determineTimeUnit(String rawUnit) {
+        switch (rawUnit.toLowerCase()) {
             case "ns":
             case "nano":
             case "nanos":
             case "nanoseconds":
-                specifiedTimeUnit = TimeUnit.NANOSECONDS;
-                break;
+                return TimeUnit.NANOSECONDS;
+            case "µs":
+            case "micro":
+            case "micros":
+            case "microseconds":
+                return TimeUnit.MICROSECONDS;
             case "ms":
             case "milli":
             case "millis":
             case "milliseconds":
-                specifiedTimeUnit = TimeUnit.MILLISECONDS;
-                break;
+                return TimeUnit.MILLISECONDS;
             case "s":
             case "sec":
             case "secs":
             case "second":
             case "seconds":
-                specifiedTimeUnit = TimeUnit.SECONDS;
-                break;
+                return TimeUnit.SECONDS;
             case "m":
             case "min":
             case "mins":
             case "minute":
             case "minutes":
-                specifiedTimeUnit = TimeUnit.MINUTES;
-                break;
+                return TimeUnit.MINUTES;
             case "h":
             case "hr":
             case "hrs":
             case "hour":
             case "hours":
-                specifiedTimeUnit = TimeUnit.HOURS;
-                break;
+                return TimeUnit.HOURS;
             case "d":
             case "day":
             case "days":
-                specifiedTimeUnit = TimeUnit.DAYS;
-                break;
-            case "w":
-            case "wk":
-            case "wks":
-            case "week":
-            case "weeks":
-                final long durationVal = Long.parseLong(duration);
-                return desiredUnit.convert(durationVal, TimeUnit.DAYS)*7;
+                return TimeUnit.DAYS;
+            default:
+                throw new IllegalArgumentException("Could not parse '" + rawUnit + "' to TimeUnit");
         }
-
-        final long durationVal = Long.parseLong(duration);
-        return desiredUnit.convert(durationVal, specifiedTimeUnit);
     }
 
     public static String formatUtilization(final double utilization) {
@@ -225,15 +392,15 @@ public class FormatUtils {
      * 3 seconds, 8 millis, 3 nanos - if includeTotalNanos = false,
      * 3 seconds, 8 millis, 3 nanos (3008000003 nanos) - if includeTotalNanos = true
      *
-     * @param nanos the number of nanoseconds to format
+     * @param nanos             the number of nanoseconds to format
      * @param includeTotalNanos whether or not to include the total number of nanoseconds in parentheses in the returned value
      * @return a human-readable String that is a formatted representation of the given number of nanoseconds.
      */
     public static String formatNanos(final long nanos, final boolean includeTotalNanos) {
         final StringBuilder sb = new StringBuilder();
 
-        final long seconds = nanos > 1000000000L ? nanos / 1000000000L : 0L;
-        long millis = nanos > 1000000L ? nanos / 1000000L : 0L;
+        final long seconds = nanos >= 1000000000L ? nanos / 1000000000L : 0L;
+        long millis = nanos >= 1000000L ? nanos / 1000000L : 0L;
         final long nanosLeft = nanos % 1000000L;
 
         if (seconds > 0) {
@@ -258,4 +425,5 @@ public class FormatUtils {
 
         return sb.toString();
     }
+
 }


[nifi-registry] 09/43: NIFIREG-325: support for node identity group - updated admin guide - adjusting PR / fixing issues found during review

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 1be492ff37fc77c5cc0f8202db34147c5bce907b
Author: Endre Zoltan Kovacs <an...@protonmail.com>
AuthorDate: Thu Oct 3 20:13:03 2019 +0200

    NIFIREG-325: support for node identity group
    - updated admin guide
    - adjusting PR / fixing issues found during review
    
    This closes #235.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 .../src/main/asciidoc/administration-guide.adoc    |  1 +
 .../file/FileAccessPolicyProvider.java             | 56 ++++++++++++++++++++++
 .../src/main/resources/conf/authorizers.xml        |  4 ++
 3 files changed, 61 insertions(+)

diff --git a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
index 765e62f..b9bc1df 100644
--- a/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-registry-core/nifi-registry-docs/src/main/asciidoc/administration-guide.adoc
@@ -348,6 +348,7 @@ The default AccessPolicyProvider is the FileAccessPolicyProvider, however, you c
 |`Authorizations File`| The file where the FileAccessPolicyProvider will store policies. By default, _authorizations.xml_ in the `conf` directory is chosen.
 |`Initial Admin Identity`| The identity of an initial admin user that will be granted access to the UI and given the ability to create additional users, groups, and policies. For example, a certificate DN, LDAP identity, or Kerberos principal.
 |`NiFi Identity`| The identity of a NiFi instance/node that will be accessing this registry. Each NiFi Identity will be granted permission to proxy user requests, as well as read any bucket to perform synchronization status checks.
+|`NiFi Group Name`| The name of the group, whose members are NiFi instance/node identities, that will be accessing this registry. The members of this group will be granted permission to proxy user requests, as well as read any bucket to perform synchronization checks.
 |==================================================================================================================================================
 
 NOTE: The identities configured in the Initial Admin Identity and NiFi Identity properties must be available in the configured User Group Provider. Initial Admin Identity and NiFi Identity properties are only read by NiFi Registry when the Authorizations File is missing or empty on startup in order to seed the initial Authorizations File.
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
index 5eb1874..8c32ab8 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/file/FileAccessPolicyProvider.java
@@ -24,6 +24,7 @@ import org.apache.nifi.registry.security.authorization.AccessPolicy;
 import org.apache.nifi.registry.security.authorization.AccessPolicyProviderInitializationContext;
 import org.apache.nifi.registry.security.authorization.AuthorizerConfigurationContext;
 import org.apache.nifi.registry.security.authorization.ConfigurableAccessPolicyProvider;
+import org.apache.nifi.registry.security.authorization.Group;
 import org.apache.nifi.registry.security.authorization.RequestAction;
 import org.apache.nifi.registry.security.authorization.User;
 import org.apache.nifi.registry.security.authorization.UserGroupProvider;
@@ -73,6 +74,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Matcher;
@@ -147,6 +149,7 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
 
     static final String PROP_NIFI_IDENTITY_PREFIX = "NiFi Identity ";
     static final String PROP_USER_GROUP_PROVIDER = "User Group Provider";
+    static final String PROP_NIFI_GROUP_NAME = "NiFi Group Name";
     static final String PROP_AUTHORIZATIONS_FILE = "Authorizations File";
     static final String PROP_INITIAL_ADMIN_IDENTITY = "Initial Admin Identity";
     static final Pattern NIFI_IDENTITY_PATTERN = Pattern.compile(PROP_NIFI_IDENTITY_PREFIX + "\\S+");
@@ -156,6 +159,7 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
     private File authorizationsFile;
     private String initialAdminIdentity;
     private Set<String> nifiIdentities;
+    private String nifiIdentityGroupIdentifier;
     private List<IdentityMapping> identityMappings;
 
     private UserGroupProvider userGroupProvider;
@@ -215,6 +219,23 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
                 }
             }
 
+            PropertyValue identityGroupNameProp = configurationContext.getProperty(PROP_NIFI_GROUP_NAME);
+            String identityGroupName = (identityGroupNameProp != null && identityGroupNameProp.isSet()) ? identityGroupNameProp.getValue() : null;
+            if (!StringUtils.isBlank(identityGroupName)) {
+                logger.debug("{} is: {}", PROP_NIFI_GROUP_NAME, identityGroupName);
+                Set<Group> groups = userGroupProvider.getGroups();
+                logger.trace("All authorization groups: {}", groups);
+                Optional<Group> identityGroupsOptional =
+                        groups.stream()
+                            .filter(group -> group.getName().equals(identityGroupName))
+                            .findFirst();
+                Group identityGroup = identityGroupsOptional
+                        .orElseThrow(() ->
+                            new SecurityProviderCreationException(String.format("Authorizations node group '%s' could not be found", identityGroupName))
+                        );
+                logger.debug("Identity Group is: {}", identityGroup);
+                nifiIdentityGroupIdentifier = identityGroup.getIdentifier();
+            }
             // load the authorizations
             load();
 
@@ -508,6 +529,13 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
                 populateNiFiIdentities(authorizations);
             }
 
+            if (!StringUtils.isEmpty(nifiIdentityGroupIdentifier)) {
+                logger.info("Populating proxy authorizations for NiFi identity group: [{}]", nifiIdentityGroupIdentifier);
+                // grant access to the resources needed for initial nifi-proxy identities
+                for (ResourceActionPair resourceAction : NIFI_ACCESS_POLICIES) {
+                    addGroupToAccessPolicy(authorizations, resourceAction.resource, nifiIdentityGroupIdentifier, resourceAction.actionCode);
+                }
+            }
             saveAndRefreshHolder(authorizations);
         } else {
             this.authorizationsHolder.set(authorizationsHolder);
@@ -564,6 +592,34 @@ public class FileAccessPolicyProvider implements ConfigurableAccessPolicyProvide
         }
     }
 
+    private void addGroupToAccessPolicy(Authorizations authorizations, String resource, String nifiIdentityGroupIdentifier, String action) {
+    Optional<Policy> policyOptional = authorizations.getPolicies().getPolicy().stream()
+            .filter(policy -> policy.getResource().equals(resource))
+            .filter(policy -> policy.getAction().equals(action))
+        .findAny();
+    if (policyOptional.isPresent()) {
+        Policy policy = policyOptional.get();
+        Policy.Group group = new Policy.Group();
+        group.setIdentifier(nifiIdentityGroupIdentifier);
+        policy.getGroup().add(group);
+    } else {
+        AccessPolicy.Builder accessPolicyBuilder =
+            new AccessPolicy.Builder()
+              .identifierGenerateFromSeed(resource + action)
+              .resource(resource)
+              .addGroup(nifiIdentityGroupIdentifier);
+      if (action.equals(READ_CODE)) {
+          accessPolicyBuilder.action(RequestAction.READ);
+      } else if (action.equals(WRITE_CODE)) {
+          accessPolicyBuilder.action(RequestAction.WRITE);
+      } else if (action.equals(DELETE_CODE)) {
+          accessPolicyBuilder.action(RequestAction.DELETE);
+      } else {
+          throw new IllegalStateException("Unknown Policy Action: " + action);
+      }
+      authorizations.getPolicies().getPolicy().add(createJAXBPolicy(accessPolicyBuilder.build()));
+    }
+  }
 
     /**
      * Creates and adds an access policy for the given resource, identity, and actions to the specified authorizations.
diff --git a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
index 26999d4..9f63754 100644
--- a/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
+++ b/nifi-registry-core/nifi-registry-resources/src/main/resources/conf/authorizers.xml
@@ -232,6 +232,9 @@
             NOTE: Any identity mapping rules specified in nifi-registry.properties will also be applied to the nifi identities,
             so the values should be the unmapped identities (i.e. full DN from a certificate). This identity must be found
             in the configured User Group Provider.
+        - NiFi Group Name: The name of the group, whose members are NiFi instance/node identities,
+            that will have access to this NiFi Registry and will be able to act as a proxy on behalf of a NiFi Registry end user.
+            The members of this group will be granted permission to proxy user requests, as well as read any bucket to perform synchronization checks.
     -->
     <accessPolicyProvider>
         <identifier>file-access-policy-provider</identifier>
@@ -239,6 +242,7 @@
         <property name="User Group Provider">file-user-group-provider</property>
         <property name="Authorizations File">./conf/authorizations.xml</property>
         <property name="Initial Admin Identity"><!-- CN=abc, OU=xyz --></property>
+        <property name="NiFi Group Name"></property>
 
         <!--<property name="NiFi Identity 1"></property>-->
     </accessPolicyProvider>


[nifi-registry] 18/43: NIFIREG-341 Make use of ASF shortened URL to point to community Slack invite link.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 74baaa9f3f33707bd0fc1ee54bbc6400923f526f
Author: Aldrin Piri <al...@apache.org>
AuthorDate: Thu Oct 24 21:33:40 2019 -0400

    NIFIREG-341 Make use of ASF shortened URL to point to community Slack invite link.
---
 nifi-registry-assembly/README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nifi-registry-assembly/README.md b/nifi-registry-assembly/README.md
index f6d1bbd..2983eb3 100644
--- a/nifi-registry-assembly/README.md
+++ b/nifi-registry-assembly/README.md
@@ -41,7 +41,7 @@ If you have questions, you can reach out to our mailing list: dev@nifi.apache.or
 
 - Apache NiFi Slack Workspace: https://apachenifi.slack.com/
 
-  New users can join the workspace using the following [invite link](https://join.slack.com/t/apachenifi/shared_invite/enQtNDI2NDMyMTY3MTA5LWJmZDI3MmM1ZmYyODQwZDYwM2MyMDY5ZjkyMDkxY2JmOGMyNmEzYTE0MTRkZTYwYzZlYTJkY2JhZTYyMzcyZGI).
+  New users can join the workspace using the following [invite link](https://s.apache.org/nifi-community-slack).
 
 - IRC: #nifi on [irc.freenode.net](http://webchat.freenode.net/?channels=#nifi)
 


[nifi-registry] 20/43: NIFIREG-252: adding mavendocker as build profile

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 35bcf4371bdadf67f49ab63eaf3aec194f39f17a
Author: Endre Zoltan Kovacs <an...@protonmail.com>
AuthorDate: Fri Oct 18 17:49:34 2019 +0200

    NIFIREG-252: adding mavendocker as build profile
    
    skip integration test if -DskipTests is set
    
    This closes #245.
    
    Signed-off-by: Kevin Doran <kd...@apache.org>
---
 nifi-registry-docker-maven/dockermaven/Dockerfile  |  73 +++++++++++++++
 .../dockermaven/integration-test.sh                |  50 ++++++++++
 nifi-registry-docker-maven/dockermaven/pom.xml     | 102 +++++++++++++++++++++
 .../dockermaven/sh/common.sh                       |  28 ++++++
 .../dockermaven/sh/secure.sh                       |  56 +++++++++++
 nifi-registry-docker-maven/dockermaven/sh/start.sh |  56 +++++++++++
 .../dockermaven/sh/update_bundle_provider.sh       |  48 ++++++++++
 .../dockermaven/sh/update_database.sh              |  24 +++++
 .../dockermaven/sh/update_flow_provider.sh         |  44 +++++++++
 .../dockermaven/sh/update_login_providers.sh       |  47 ++++++++++
 nifi-registry-docker-maven/pom.xml                 |  33 +++++++
 pom.xml                                            |   1 +
 12 files changed, 562 insertions(+)

diff --git a/nifi-registry-docker-maven/dockermaven/Dockerfile b/nifi-registry-docker-maven/dockermaven/Dockerfile
new file mode 100644
index 0000000..945cb80
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/Dockerfile
@@ -0,0 +1,73 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+FROM openjdk:8-jre AS artifactbase
+LABEL maintainer="Apache NiFi <de...@nifi.apache.org>"
+
+ARG NIFI_REGISTRY_BINARY
+ARG NIFI_REGISTRY_VERSION=1.0.0
+
+ENV NIFI_REGISTRY_BASE_DIR /opt/nifi-registry
+ENV NIFI_REGISTRY_HOME ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-current
+
+ADD sh/ ${NIFI_REGISTRY_BASE_DIR}/scripts/
+
+COPY $NIFI_REGISTRY_BINARY $NIFI_REGISTRY_BASE_DIR
+RUN unzip ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.zip -d ${NIFI_REGISTRY_BASE_DIR} \
+    && rm ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}-bin.zip \
+    && mv ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION} ${NIFI_REGISTRY_HOME} \
+    && ln -s ${NIFI_REGISTRY_HOME} ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${NIFI_REGISTRY_VERSION}
+
+
+FROM openjdk:8-jre
+LABEL maintainer="Apache NiFi Registry <de...@nifi.apache.org>"
+LABEL site="https://nifi.apache.org"
+
+ARG UID=1000
+ARG GID=1000
+
+ENV NIFI_REGISTRY_BASE_DIR /opt/nifi-registry
+ENV NIFI_REGISTRY_HOME ${NIFI_REGISTRY_BASE_DIR}/nifi-registry-current
+
+COPY --chown=${UID}:${GID} --from=artifactbase $NIFI_REGISTRY_BASE_DIR $NIFI_REGISTRY_BASE_DIR
+
+# Setup NiFi user and create necessary directories
+RUN groupadd -g ${GID} nifi || groupmod -n nifi `getent group ${GID} | cut -d: -f1` \
+    && useradd --shell /bin/bash -u ${UID} -g ${GID} -m nifi \
+    && chown -R nifi:nifi ${NIFI_REGISTRY_BASE_DIR} \
+    && apt-get update \
+    && apt-get install -y jq xmlstarlet procps
+
+
+USER nifi
+
+# Web HTTP(s) ports
+EXPOSE 18080 18443
+
+WORKDIR ${NIFI_REGISTRY_HOME}
+
+# Apply configuration and start NiFi
+#
+# We need to use the exec form to avoid running our command in a subshell and omitting signals,
+# thus being unable to shut down gracefully:
+# https://docs.docker.com/engine/reference/builder/#entrypoint
+#
+# Also we need to use relative path, because the exec form does not invoke a command shell,
+# thus normal shell processing does not happen:
+# https://docs.docker.com/engine/reference/builder/#exec-form-entrypoint-example
+ENTRYPOINT ["../scripts/start.sh"]
diff --git a/nifi-registry-docker-maven/dockermaven/integration-test.sh b/nifi-registry-docker-maven/dockermaven/integration-test.sh
new file mode 100755
index 0000000..54e2672
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/integration-test.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+set -exuo pipefail
+
+TAG=$1
+VERSION=$2
+
+container_name=nifi-registry-${TAG}-integration-test
+
+trap "{ docker ps -qaf Name=${container_name} | xargs docker rm -f; }" EXIT
+
+echo "Checking that all files are owned by NiFi"
+test -z $(docker run --rm --entrypoint /bin/bash apache/nifi-registry:${TAG} -c "find /opt/nifi-registry ! -user nifi")
+
+echo "Checking environment variables"
+test "/opt/nifi-registry/nifi-registry-current" = "$(docker run --rm --entrypoint /bin/bash apache/nifi-registry:${TAG} -c 'echo -n $NIFI_REGISTRY_HOME')"
+test "/opt/nifi-registry/nifi-registry-current" = "$(docker run --rm --entrypoint /bin/bash apache/nifi-registry:${TAG} -c "readlink \${NIFI_REGISTRY_BASE_DIR}/nifi-registry-${VERSION}")"
+
+test "/opt/nifi-registry" = "$(docker run --rm --entrypoint /bin/bash apache/nifi-registry:${TAG} -c 'echo -n $NIFI_REGISTRY_BASE_DIR')"
+
+echo "Starting NiFi Registry container..."
+
+docker run -d --name ${container_name} apache/nifi-registry:${TAG}
+
+IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ${container_name})
+
+for i in $(seq 1 10) :; do
+    if docker exec ${container_name} bash -c "ss -ntl | grep 18080"; then
+        break
+    fi
+    sleep 10
+done
+
+echo "Stopping NiFi Registry container"
+time docker stop ${container_name}
diff --git a/nifi-registry-docker-maven/dockermaven/pom.xml b/nifi-registry-docker-maven/dockermaven/pom.xml
new file mode 100644
index 0000000..4b00044
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+    license agreements. See the NOTICE file distributed with this work for additional
+    information regarding copyright ownership. The ASF licenses this file to
+    You 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>nifi-registry-docker-maven</artifactId>
+        <groupId>org.apache.nifi.registry</groupId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <artifactId>dockermaven</artifactId>
+
+    <profiles>
+        <profile>
+            <id>docker</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>com.spotify</groupId>
+                        <artifactId>dockerfile-maven-plugin</artifactId>
+                        <version>1.3.5</version>
+                        <executions>
+                            <execution>
+                                <id>default</id>
+                                <goals>
+                                    <goal>build</goal>
+                                </goals>
+                                <configuration>
+                                    <buildArgs>
+                                        <UID>1000</UID>
+                                        <GID>1000</GID>
+                                        <NIFI_REGISTRY_VERSION>${project.version}</NIFI_REGISTRY_VERSION>
+                                        <NIFI_REGISTRY_BINARY>target/nifi-registry-${project.version}-bin.zip</NIFI_REGISTRY_BINARY>
+                                    </buildArgs>
+                                    <repository>apache/nifi-registry</repository>
+                                    <tag>${project.version}-dockermaven</tag>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <!-- Copy generated artifacts -->
+                    <plugin>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <version>1.8</version>
+                        <executions>
+                            <execution>
+                                <id>copy-for-docker</id>
+                                <phase>process-sources</phase>
+                                <configuration>
+                                    <target name="copy assembly to nifi-registry-docker for image build">
+                                        <copy todir="${project.basedir}/target" overwrite="true" flatten="true">
+                                            <fileset dir="${project.basedir}/../../nifi-registry-assembly/target" includes="*.zip">
+                                                <include name="*.zip" />
+                                            </fileset>
+                                        </copy>
+                                    </target>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                    <plugin>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <executions>
+                            <execution>
+                                <id>Docker integration tests</id>
+                                <phase>integration-test</phase>
+                                <goals>
+                                    <goal>exec</goal>
+                                </goals>
+                                <configuration>
+                                    <skip>${skipTests}</skip>
+                                    <arguments>
+                                        <argument>${project.version}-dockermaven</argument>
+                                        <argument>${project.version}</argument>
+                                    </arguments>
+                                    <executable>${project.basedir}/integration-test.sh</executable>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/nifi-registry-docker-maven/dockermaven/sh/common.sh b/nifi-registry-docker-maven/dockermaven/sh/common.sh
new file mode 100755
index 0000000..0f594d9
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/common.sh
@@ -0,0 +1,28 @@
+#!/bin/sh -e
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+# 1 - value to search for
+# 2 - value to replace
+# 3 - file to perform replacement inline
+prop_replace () {
+  target_file=${3:-${nifi_registry_props_file}}
+  echo 'replacing target file ' ${target_file}
+  sed -i -e "s|^$1=.*$|$1=$2|"  ${target_file}
+}
+
+# NIFI_REGISTRY_HOME is defined by an ENV command in the backing Dockerfile
+export nifi_registry_props_file=${NIFI_REGISTRY_HOME}/conf/nifi-registry.properties
+export hostname=$(hostname)
diff --git a/nifi-registry-docker-maven/dockermaven/sh/secure.sh b/nifi-registry-docker-maven/dockermaven/sh/secure.sh
new file mode 100644
index 0000000..352dfad
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/secure.sh
@@ -0,0 +1,56 @@
+#!/bin/sh -e
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+scripts_dir='/opt/nifi-registry/scripts'
+
+[ -f "${scripts_dir}/common.sh" ] && . "${scripts_dir}/common.sh"
+
+# Perform idempotent changes of configuration to support secure environments
+echo 'Configuring environment with SSL settings'
+
+: ${KEYSTORE_PATH:?"Must specify an absolute path to the keystore being used."}
+if [ ! -f "${KEYSTORE_PATH}" ]; then
+    echo "Keystore file specified (${KEYSTORE_PATH}) does not exist."
+    exit 1
+fi
+: ${KEYSTORE_TYPE:?"Must specify the type of keystore (JKS, PKCS12, PEM) of the keystore being used."}
+: ${KEYSTORE_PASSWORD:?"Must specify the password of the keystore being used."}
+
+: ${TRUSTSTORE_PATH:?"Must specify an absolute path to the truststore being used."}
+if [ ! -f "${TRUSTSTORE_PATH}" ]; then
+    echo "Keystore file specified (${TRUSTSTORE_PATH}) does not exist."
+    exit 1
+fi
+: ${TRUSTSTORE_TYPE:?"Must specify the type of truststore (JKS, PKCS12, PEM) of the truststore being used."}
+: ${TRUSTSTORE_PASSWORD:?"Must specify the password of the truststore being used."}
+
+prop_replace 'nifi.registry.security.keystore'           "${KEYSTORE_PATH}"
+prop_replace 'nifi.registry.security.keystoreType'       "${KEYSTORE_TYPE}"
+prop_replace 'nifi.registry.security.keystorePasswd'     "${KEYSTORE_PASSWORD}"
+prop_replace 'nifi.registry.security.truststore'         "${TRUSTSTORE_PATH}"
+prop_replace 'nifi.registry.security.truststoreType'     "${TRUSTSTORE_TYPE}"
+prop_replace 'nifi.registry.security.truststorePasswd'   "${TRUSTSTORE_PASSWORD}"
+
+# Disable HTTP and enable HTTPS
+prop_replace 'nifi.registry.web.http.port'   ''
+prop_replace 'nifi.registry.web.http.host'   ''
+prop_replace 'nifi.registry.web.https.port'  "${NIFI_REGISTRY_WEB_HTTPS_PORT:-18443}"
+prop_replace 'nifi.registry.web.https.host'  "${NIFI_REGISTRY_WEB_HTTPS_HOST:-$HOSTNAME}"
+
+# Establish initial user and an associated admin identity
+sed -i -e 's|<property name="Initial User Identity 1">.*</property>|<property name="Initial User Identity 1">'"${INITIAL_ADMIN_IDENTITY}"'</property>|'  ${NIFI_REGISTRY_HOME}/conf/authorizers.xml
+sed -i -e 's|<property name="Initial Admin Identity">.*</property>|<property name="Initial Admin Identity">'"${INITIAL_ADMIN_IDENTITY}"'</property>|'  ${NIFI_REGISTRY_HOME}/conf/authorizers.xml
diff --git a/nifi-registry-docker-maven/dockermaven/sh/start.sh b/nifi-registry-docker-maven/dockermaven/sh/start.sh
new file mode 100755
index 0000000..c65f3ea
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/start.sh
@@ -0,0 +1,56 @@
+#!/bin/sh -e
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+scripts_dir='/opt/nifi-registry/scripts'
+
+[ -f "${scripts_dir}/common.sh" ] && . "${scripts_dir}/common.sh"
+
+# Establish baseline properties
+prop_replace 'nifi.registry.web.http.port'      "${NIFI_REGISTRY_WEB_HTTP_PORT:-18080}"
+prop_replace 'nifi.registry.web.http.host'      "${NIFI_REGISTRY_WEB_HTTP_HOST:-$HOSTNAME}"
+
+. ${scripts_dir}/update_database.sh
+
+# Check if we are secured or unsecured
+case ${AUTH} in
+    tls)
+        echo 'Enabling Two-Way SSL user authentication'
+        . "${scripts_dir}/secure.sh"
+        ;;
+    ldap)
+        echo 'Enabling LDAP user authentication'
+        # Reference ldap-provider in properties
+        prop_replace 'nifi.registry.security.identity.provider' 'ldap-identity-provider'
+        prop_replace 'nifi.registry.security.needClientAuth' 'false'
+
+        . "${scripts_dir}/secure.sh"
+        . "${scripts_dir}/update_login_providers.sh"
+        ;;
+esac
+
+. "${scripts_dir}/update_flow_provider.sh"
+. "${scripts_dir}/update_bundle_provider.sh"
+
+# Continuously provide logs so that 'docker logs' can produce them
+tail -F "${NIFI_REGISTRY_HOME}/logs/nifi-registry-app.log" &
+"${NIFI_REGISTRY_HOME}/bin/nifi-registry.sh" run &
+nifi_registry_pid="$!"
+
+trap "echo Received trapped signal, beginning shutdown...;" KILL TERM HUP INT EXIT;
+
+echo NiFi-Registry running with PID ${nifi_registry_pid}.
+wait ${nifi_registry_pid}
\ No newline at end of file
diff --git a/nifi-registry-docker-maven/dockermaven/sh/update_bundle_provider.sh b/nifi-registry-docker-maven/dockermaven/sh/update_bundle_provider.sh
new file mode 100644
index 0000000..27d5c94
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/update_bundle_provider.sh
@@ -0,0 +1,48 @@
+#!/bin/sh -e
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+providers_file=${NIFI_REGISTRY_HOME}/conf/providers.xml
+property_xpath='/providers/extensionBundlePersistenceProvider'
+
+add_property() {
+  property_name=$1
+  property_value=$2
+
+  if [ -n "${property_value}" ]; then
+    xmlstarlet ed --inplace --subnode "${property_xpath}" --type elem -n property -v "${property_value}" \
+      -i \$prev --type attr -n name -v "${property_name}" \
+      "${providers_file}"
+  fi
+}
+
+xmlstarlet ed --inplace -u "${property_xpath}/property[@name='Extension Bundle Storage Directory']" -v "${NIFI_REGISTRY_BUNDLE_STORAGE_DIR:-./extension_bundles}" "${providers_file}"
+
+case ${NIFI_REGISTRY_BUNDLE_PROVIDER} in
+    file)
+        xmlstarlet ed --inplace -u "${property_xpath}/class" -v "org.apache.nifi.registry.provider.extension.FileSystemBundlePersistenceProvider" "${providers_file}"
+        ;;
+    s3)
+        xmlstarlet ed --inplace -u "${property_xpath}/class" -v "org.apache.nifi.registry.aws.S3BundlePersistenceProvider" "${providers_file}"
+        add_property "Region"                "${NIFI_REGISTRY_S3_REGION:-}"
+        add_property "Bucket Name"           "${NIFI_REGISTRY_S3_BUCKET_NAME:-}"
+        add_property "Key Prefix"            "${NIFI_REGISTRY_S3_KEY_PREFIX:-}"
+        add_property "Credentials Provider"  "${NIFI_REGISTRY_S3_CREDENTIALS_PROVIDER:-DEFAULT_CHAIN}"
+        add_property "Access Key"            "${NIFI_REGISTRY_S3_ACCESS_KEY:-}"
+        add_property "Secret Access Key"     "${NIFI_REGISTRY_S3_SECRET_ACCESS_KEY:-}"
+        add_property "Endpoint URL"          "${NIFI_REGISTRY_S3_ENDPOINT_URL:-}"
+        ;;
+esac
diff --git a/nifi-registry-docker-maven/dockermaven/sh/update_database.sh b/nifi-registry-docker-maven/dockermaven/sh/update_database.sh
new file mode 100644
index 0000000..59d94d7
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/update_database.sh
@@ -0,0 +1,24 @@
+#!/bin/sh -e
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+prop_replace 'nifi.registry.db.url'                         "${NIFI_REGISTRY_DB_URL:-jdbc:h2:./database/nifi-registry-primary;AUTOCOMMIT=OFF;DB_CLOSE_ON_EXIT=FALSE;LOCK_MODE=3;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE}"
+prop_replace 'nifi.registry.db.driver.class'                "${NIFI_REGISTRY_DB_CLASS:-org.h2.Driver}"
+prop_replace 'nifi.registry.db.driver.directory'            "${NIFI_REGISTRY_DB_DIR:-}"
+prop_replace 'nifi.registry.db.username'                    "${NIFI_REGISTRY_DB_USER:-nifireg}"
+prop_replace 'nifi.registry.db.password'                    "${NIFI_REGISTRY_DB_PASS:-nifireg}"
+prop_replace 'nifi.registry.db.maxConnections'              "${NIFI_REGISTRY_DB_MAX_CONNS:-5}"
+prop_replace 'nifi.registry.db.sql.debug'                   "${NIFI_REGISTRY_DB_DEBUG_SQL:-false}"
diff --git a/nifi-registry-docker-maven/dockermaven/sh/update_flow_provider.sh b/nifi-registry-docker-maven/dockermaven/sh/update_flow_provider.sh
new file mode 100644
index 0000000..c903323
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/update_flow_provider.sh
@@ -0,0 +1,44 @@
+#!/bin/sh -e
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+providers_file=${NIFI_REGISTRY_HOME}/conf/providers.xml
+property_xpath='/providers/flowPersistenceProvider'
+
+add_property() {
+  property_name=$1
+  property_value=$2
+
+  if [ -n "${property_value}" ]; then
+    xmlstarlet ed --inplace --subnode "${property_xpath}" --type elem -n property -v "${property_value}" \
+      -i \$prev --type attr -n name -v "${property_name}" \
+      "${providers_file}"
+  fi
+}
+
+xmlstarlet ed --inplace -u "${property_xpath}/property[@name='Flow Storage Directory']" -v "${NIFI_REGISTRY_FLOW_STORAGE_DIR:-./flow_storage}" "${providers_file}"
+
+case ${NIFI_REGISTRY_FLOW_PROVIDER} in
+    file)
+        xmlstarlet ed --inplace -u "${property_xpath}/class" -v "org.apache.nifi.registry.provider.flow.FileSystemFlowPersistenceProvider" "${providers_file}"
+        ;;
+    git)
+        xmlstarlet ed --inplace -u "${property_xpath}/class" -v "org.apache.nifi.registry.provider.flow.git.GitFlowPersistenceProvider" "${providers_file}"
+        add_property "Remote To Push"  "${NIFI_REGISTRY_GIT_REMOTE:-}"
+        add_property "Remote Access User"  "${NIFI_REGISTRY_GIT_USER:-}"
+        add_property "Remote Access Password"    "${NIFI_REGISTRY_GIT_PASSWORD:-}"
+        ;;
+esac
diff --git a/nifi-registry-docker-maven/dockermaven/sh/update_login_providers.sh b/nifi-registry-docker-maven/dockermaven/sh/update_login_providers.sh
new file mode 100755
index 0000000..e3280b5
--- /dev/null
+++ b/nifi-registry-docker-maven/dockermaven/sh/update_login_providers.sh
@@ -0,0 +1,47 @@
+#!/bin/sh -e
+
+#    Licensed to the Apache Software Foundation (ASF) under one or more
+#    contributor license agreements.  See the NOTICE file distributed with
+#    this work for additional information regarding copyright ownership.
+#    The ASF licenses this file to You 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.
+
+login_providers_file=${NIFI_REGISTRY_HOME}/conf/identity-providers.xml
+property_xpath='//identityProviders/provider/property'
+
+# Update a given property in the login-identity-providers file if a value is specified
+edit_property() {
+  property_name=$1
+  property_value=$2
+
+  if [ -n "${property_value}" ]; then
+    xmlstarlet ed --inplace -u "${property_xpath}[@name='${property_name}']" -v "${property_value}" "${login_providers_file}"
+  fi
+}
+
+# Remove comments to enable the ldap-provider
+sed -i '/To enable the ldap-identity-provider remove/d' "${login_providers_file}"
+
+edit_property 'Authentication Strategy'     "${LDAP_AUTHENTICATION_STRATEGY}"
+edit_property 'Manager DN'                  "${LDAP_MANAGER_DN}"
+edit_property 'Manager Password'            "${LDAP_MANAGER_PASSWORD}"
+edit_property 'TLS - Keystore'              "${LDAP_TLS_KEYSTORE}"
+edit_property 'TLS - Keystore Password'     "${LDAP_TLS_KEYSTORE_PASSWORD}"
+edit_property 'TLS - Keystore Type'         "${LDAP_TLS_KEYSTORE_TYPE}"
+edit_property 'TLS - Truststore'            "${LDAP_TLS_TRUSTSTORE}"
+edit_property 'TLS - Truststore Password'   "${LDAP_TLS_TRUSTSTORE_PASSWORD}"
+edit_property 'TLS - Truststore Type'       "${LDAP_TLS_TRUSTSTORE_TYPE}"
+edit_property 'TLS - Protocol'              "${LDAP_TLS_PROTOCOL}"
+edit_property 'Url'                         "${LDAP_URL}"
+edit_property 'User Search Base'            "${LDAP_USER_SEARCH_BASE}"
+edit_property 'User Search Filter'          "${LDAP_USER_SEARCH_FILTER}"
+edit_property 'Identity Strategy'           "${LDAP_IDENTITY_STRATEGY}"
diff --git a/nifi-registry-docker-maven/pom.xml b/nifi-registry-docker-maven/pom.xml
new file mode 100644
index 0000000..3e9b405
--- /dev/null
+++ b/nifi-registry-docker-maven/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.nifi.registry</groupId>
+        <artifactId>nifi-registry</artifactId>
+        <version>1.0.0-SNAPSHOT</version>
+    </parent>
+    
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>pom</packaging>
+    
+    <artifactId>nifi-registry-docker-maven</artifactId>
+    <groupId>org.apache.nifi.registry</groupId>
+    <version>1.0.0-SNAPSHOT</version>
+
+    <modules>
+        <module>dockermaven</module>
+    </modules>
+</project>
diff --git a/pom.xml b/pom.xml
index c02025c..74067bd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
         <module>nifi-registry-extensions</module>
         <module>nifi-registry-assembly</module>
         <module>nifi-registry-toolkit</module>
+        <module>nifi-registry-docker-maven</module>
     </modules>
     <url>https://nifi.apache.org/registry.html</url>
     <organization>


[nifi-registry] 28/43: NIFIREG-357 Added autocomplete="off" to login password input.

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit cc472962afbba672fdc5eab98931fcb3ef342a66
Author: mtien <mt...@gmail.com>
AuthorDate: Tue Feb 18 13:24:39 2020 -0800

    NIFIREG-357 Added autocomplete="off" to login password input.
---
 .../main/webapp/components/login/dialogs/nf-registry-user-login.html    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/login/dialogs/nf-registry-user-login.html b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/login/dialogs/nf-registry-user-login.html
index eee4614..e873e47 100644
--- a/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/login/dialogs/nf-registry-user-login.html
+++ b/nifi-registry-core/nifi-registry-web-ui/src/main/webapp/components/login/dialogs/nf-registry-user-login.html
@@ -32,7 +32,7 @@ limitations under the License.
         </div>
         <div class="fill-available-width">
             <mat-form-field floatLabel="always" fxFlex>
-                <input #passwordInput type="password" matInput floatPlaceholder="always" placeholder="Password">
+                <input #passwordInput type="password" matInput floatPlaceholder="always" placeholder="Password" autocomplete="off">
             </mat-form-field>
         </div>
     </div>


[nifi-registry] 42/43: NIFIREG-370 Ensuring update retrieves the latest revision from RevisionManager

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 17cecb04e87661d0412a6fb8437593fef8c1d44a
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Wed Mar 11 15:51:21 2020 -0400

    NIFIREG-370 Ensuring update retrieves the latest revision from RevisionManager
    
    This closes #266.
    
    Signed-off-by: Kevin Doran <kd...@apache.org>
---
 .../entity/StandardRevisableEntityService.java     | 53 +++++++++++++---------
 .../entity/TestStandardRevisableEntityService.java | 28 ++++++++++++
 2 files changed, 60 insertions(+), 21 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/main/java/org/apache/nifi/registry/revision/entity/StandardRevisableEntityService.java b/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/main/java/org/apache/nifi/registry/revision/entity/StandardRevisableEntityService.java
index cd55ea3..8c4f2cf 100644
--- a/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/main/java/org/apache/nifi/registry/revision/entity/StandardRevisableEntityService.java
+++ b/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/main/java/org/apache/nifi/registry/revision/entity/StandardRevisableEntityService.java
@@ -57,7 +57,22 @@ public class StandardRevisableEntityService implements RevisableEntityService {
             throw new IllegalArgumentException("Creator identity is required");
         }
 
-        return createOrUpdate(requestEntity, creatorIdentity, createEntity);
+        final Revision revision = createRevision(requestEntity.getIdentifier(), requestEntity.getRevision());
+        final RevisionClaim claim = new StandardRevisionClaim(revision);
+
+        final RevisionUpdate<T> revisionUpdate = revisionManager.updateRevision(claim, () -> {
+            final T updatedEntity = createEntity.get();
+
+            final Revision updatedRevision = revision.incrementRevision(revision.getClientId());
+            final EntityModification entityModification = new EntityModification(updatedRevision, creatorIdentity);
+
+            final RevisionInfo updatedRevisionInfo = createRevisionInfo(updatedRevision, entityModification);
+            updatedEntity.setRevision(updatedRevisionInfo);
+
+            return new StandardRevisionUpdate<>(updatedEntity, entityModification);
+        });
+
+        return revisionUpdate.getEntity();
     }
 
     @Override
@@ -90,7 +105,22 @@ public class StandardRevisableEntityService implements RevisableEntityService {
             throw new IllegalArgumentException("Updater identity is required");
         }
 
-        return createOrUpdate(requestEntity, updaterIdentity, updateEntity);
+        final Revision revision = createRevision(requestEntity.getIdentifier(), requestEntity.getRevision());
+        final RevisionClaim claim = new StandardRevisionClaim(revision);
+
+        final RevisionUpdate<T> revisionUpdate = revisionManager.updateRevision(claim, () -> {
+            final T updatedEntity = updateEntity.get();
+
+            final Revision updatedRevision = revisionManager.getRevision(requestEntity.getIdentifier()).incrementRevision(revision.getClientId());
+            final EntityModification entityModification = new EntityModification(updatedRevision, updaterIdentity);
+
+            final RevisionInfo updatedRevisionInfo = createRevisionInfo(updatedRevision, entityModification);
+            updatedEntity.setRevision(updatedRevisionInfo);
+
+            return new StandardRevisionUpdate<>(updatedEntity, entityModification);
+        });
+
+        return revisionUpdate.getEntity();
     }
 
     @Override
@@ -108,25 +138,6 @@ public class StandardRevisableEntityService implements RevisableEntityService {
         return revisionManager.deleteRevision(claim, () -> deleteEntity.get());
     }
 
-    private <T extends RevisableEntity> T createOrUpdate(final T requestEntity, final String userIdentity, final Supplier<T> updateOrCreateEntity) {
-        final Revision revision = createRevision(requestEntity.getIdentifier(), requestEntity.getRevision());
-        final RevisionClaim claim = new StandardRevisionClaim(revision);
-
-        final RevisionUpdate<T> revisionUpdate = revisionManager.updateRevision(claim, () -> {
-            final T updatedEntity = updateOrCreateEntity.get();
-
-            final Revision updatedRevision = revision.incrementRevision(revision.getClientId());
-            final EntityModification entityModification = new EntityModification(updatedRevision, userIdentity);
-
-            final RevisionInfo updatedRevisionInfo = createRevisionInfo(updatedRevision, entityModification);
-            updatedEntity.setRevision(updatedRevisionInfo);
-
-            return new StandardRevisionUpdate<>(updatedEntity, entityModification);
-        });
-
-        return revisionUpdate.getEntity();
-    }
-
     private <T extends RevisableEntity> void populateRevisions(final Collection<T> revisableEntities) {
         if (revisableEntities == null) {
             return;
diff --git a/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/test/java/org/apache/nifi/registry/revision/entity/TestStandardRevisableEntityService.java b/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/test/java/org/apache/nifi/registry/revision/entity/TestStandardRevisableEntityService.java
index 47b3d9c..0458d5c 100644
--- a/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/test/java/org/apache/nifi/registry/revision/entity/TestStandardRevisableEntityService.java
+++ b/nifi-registry-core/nifi-registry-revision/nifi-registry-revision-entity-service/src/test/java/org/apache/nifi/registry/revision/entity/TestStandardRevisableEntityService.java
@@ -133,6 +133,34 @@ public class TestStandardRevisableEntityService {
         assertEquals("user2", updatedEntity.getRevision().getLastModifier());
     }
 
+    @Test
+    public void testUpdateWithClientId() {
+        final RevisionInfo revisionInfo = new RevisionInfo("client-1", 0L);
+        final TestEntity requestEntity = new TestEntity("1", revisionInfo);
+
+        final RevisableEntity createdEntity = entityService.create(
+                requestEntity, "user1", () -> requestEntity);
+        assertNotNull(createdEntity);
+        assertEquals(requestEntity.getIdentifier(), createdEntity.getIdentifier());
+        assertNotNull(createdEntity.getRevision());
+        assertEquals(1, createdEntity.getRevision().getVersion().longValue());
+
+        final RevisableEntity updatedEntity = entityService.update(
+                createdEntity, "user2", () -> createdEntity);
+        assertNotNull(updatedEntity.getRevision());
+        assertEquals(2, updatedEntity.getRevision().getVersion().longValue());
+        assertEquals("user2", updatedEntity.getRevision().getLastModifier());
+
+        // set the version back to 0 to prove that we can update based on client id being the same
+        updatedEntity.getRevision().setVersion(0L);
+
+        final RevisableEntity updatedEntity2 = entityService.update(
+                createdEntity, "user3", () -> updatedEntity);
+        assertNotNull(updatedEntity2.getRevision());
+        assertEquals(3, updatedEntity2.getRevision().getVersion().longValue());
+        assertEquals("user3", updatedEntity2.getRevision().getLastModifier());
+    }
+
     @Test(expected = IllegalArgumentException.class)
     public void testUpdateWhenMissingRevision() {
         final RevisionInfo revisionInfo = new RevisionInfo(null, 0L);


[nifi-registry] 41/43: NIFIREG-369 Set file mode to 0664 for lib directories in assembly

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit abe65545a6ec62de8b332aadc4e1afe7b55c1ba1
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Mon Mar 9 09:23:10 2020 -0400

    NIFIREG-369 Set file mode to 0664 for lib directories in assembly
---
 nifi-registry-assembly/src/main/assembly/dependencies.xml           | 6 +++---
 .../nifi-registry-aws-assembly/src/main/assembly/extension.xml      | 2 +-
 .../nifi-registry-ranger-assembly/src/main/assembly/extension.xml   | 2 +-
 .../src/main/assembly/dependencies.xml                              | 2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/nifi-registry-assembly/src/main/assembly/dependencies.xml b/nifi-registry-assembly/src/main/assembly/dependencies.xml
index da25c39..0f0d39c 100644
--- a/nifi-registry-assembly/src/main/assembly/dependencies.xml
+++ b/nifi-registry-assembly/src/main/assembly/dependencies.xml
@@ -30,7 +30,7 @@
             <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>lib/shared</outputDirectory>
             <directoryMode>0770</directoryMode>
-            <fileMode>0660</fileMode>
+            <fileMode>0664</fileMode>
             <useTransitiveFiltering>true</useTransitiveFiltering>
             <includes>
                 <include>nifi-registry-utils</include>
@@ -44,7 +44,7 @@
             <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>lib/bootstrap</outputDirectory>
             <directoryMode>0770</directoryMode>
-            <fileMode>0660</fileMode>
+            <fileMode>0664</fileMode>
             <useTransitiveFiltering>true</useTransitiveFiltering>
             <includes>
                 <include>nifi-registry-bootstrap</include>
@@ -74,7 +74,7 @@
             <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>lib</outputDirectory>
             <directoryMode>0770</directoryMode>
-            <fileMode>0660</fileMode>
+            <fileMode>0664</fileMode>
             <useTransitiveFiltering>true</useTransitiveFiltering>
             <excludes>
                 <exclude>nifi-registry-resources</exclude>
diff --git a/nifi-registry-extensions/nifi-registry-aws/nifi-registry-aws-assembly/src/main/assembly/extension.xml b/nifi-registry-extensions/nifi-registry-aws/nifi-registry-aws-assembly/src/main/assembly/extension.xml
index 87f2e0f..6fb09fb 100644
--- a/nifi-registry-extensions/nifi-registry-aws/nifi-registry-aws-assembly/src/main/assembly/extension.xml
+++ b/nifi-registry-extensions/nifi-registry-aws/nifi-registry-aws-assembly/src/main/assembly/extension.xml
@@ -25,7 +25,7 @@
             <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>lib</outputDirectory>
             <directoryMode>0770</directoryMode>
-            <fileMode>0660</fileMode>
+            <fileMode>0664</fileMode>
         </dependencySet>
     </dependencySets>
 
diff --git a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-assembly/src/main/assembly/extension.xml b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-assembly/src/main/assembly/extension.xml
index 2db464d..859ca11 100644
--- a/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-assembly/src/main/assembly/extension.xml
+++ b/nifi-registry-extensions/nifi-registry-ranger/nifi-registry-ranger-assembly/src/main/assembly/extension.xml
@@ -25,7 +25,7 @@
             <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>lib</outputDirectory>
             <directoryMode>0770</directoryMode>
-            <fileMode>0660</fileMode>
+            <fileMode>0664</fileMode>
         </dependencySet>
     </dependencySets>
 
diff --git a/nifi-registry-toolkit/nifi-registry-toolkit-assembly/src/main/assembly/dependencies.xml b/nifi-registry-toolkit/nifi-registry-toolkit-assembly/src/main/assembly/dependencies.xml
index a5ac13f..7aa0a35 100644
--- a/nifi-registry-toolkit/nifi-registry-toolkit-assembly/src/main/assembly/dependencies.xml
+++ b/nifi-registry-toolkit/nifi-registry-toolkit-assembly/src/main/assembly/dependencies.xml
@@ -31,7 +31,7 @@
             <outputDirectory>lib</outputDirectory>
             <useProjectArtifact>false</useProjectArtifact>
             <directoryMode>0770</directoryMode>
-            <fileMode>0660</fileMode>
+            <fileMode>0664</fileMode>
         </dependencySet>
     </dependencySets>
     <fileSets>


[nifi-registry] 24/43: NIFIREG-354 - updated toString to allow for null snapshot metadata, which can happen when using this class to represent an unversioned flow outside of the NiFi Registry context

Posted by ab...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

aboda pushed a commit to branch NIFIREG-371-RC1
in repository https://gitbox.apache.org/repos/asf/nifi-registry.git

commit 859b75eeb679558f94fc063347647857abac2631
Author: jsferner <jo...@gmail.com>
AuthorDate: Thu Jan 23 12:13:52 2020 -0500

    NIFIREG-354 - updated toString to allow for null snapshot metadata, which can happen when using this class to represent an unversioned flow outside of the NiFi Registry context
---
 .../nifi/registry/flow/VersionedFlowSnapshot.java   | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
index 4611b9e..bf6ad98 100644
--- a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/flow/VersionedFlowSnapshot.java
@@ -35,6 +35,11 @@ import java.util.Objects;
  * is saved as a snapshot, representing information such as the name of the flow, the
  * version of the flow, the timestamp when it was saved, the contents of the flow, etc.
  * </p>
+ * <p>
+ * With the advent of download and upload flow in NiFi, this class is now used outside of
+ * NiFi Registry to represent a snapshot of an unversioned flow, which is purely the
+ * flow contents without any versioning or snapshot metadata.
+ * </p>
  */
 @ApiModel
 @XmlRootElement
@@ -52,7 +57,7 @@ public class VersionedFlowSnapshot {
     private Map<String,ExternalControllerServiceReference> externalControllerServices;
 
     // optional parameter contexts mapped by their name
-    private Map<String,VersionedParameterContext> parameterContexts;;
+    private Map<String,VersionedParameterContext> parameterContexts;
 
     // optional encoding version that clients may specify to track how the flow contents are encoded
     private String flowEncodingVersion;
@@ -159,8 +164,14 @@ public class VersionedFlowSnapshot {
 
     @Override
     public String toString() {
-        final String flowName = (flow == null ? "null" : flow.getName());
-        return "VersionedFlowSnapshot[flowId=" + snapshotMetadata.getFlowIdentifier() + ", flowName=" + flowName
-            + ", version=" + snapshotMetadata.getVersion() + ", comments=" + snapshotMetadata.getComments() + "]";
+        // snapshotMetadata and flow will be null when this is used to represent an unversioned flow
+        if (snapshotMetadata == null) {
+            return "VersionedFlowSnapshot[flowContentsId=" + flowContents.getIdentifier() + ", flowContentsName="
+                    + flowContents.getName() + ", NoMetadataAvailable]";
+        } else {
+            final String flowName = (flow == null ? "null" : flow.getName());
+            return "VersionedFlowSnapshot[flowId=" + snapshotMetadata.getFlowIdentifier() + ", flowName=" + flowName
+                    + ", version=" + snapshotMetadata.getVersion() + ", comments=" + snapshotMetadata.getComments() + "]";
+        }
     }
-}
+}
\ No newline at end of file