diff --git a/.gitignore b/.gitignore index b7e2accd..6afb33d1 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,14 @@ static/fonts # font files originate from a node module static/fonts/* +static/assets +static/assets/* + # local log files log/* config/dev.ini + +# CRLs +/crl +/crl-tmp diff --git a/.travis.yml b/.travis.yml index 02dab0db..94b83396 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ sudo: required language: python python: "3.6" -services: docker +services: + - docker git: submodules: false env: @@ -10,17 +11,22 @@ env: - PROD_IMAGE_NAME=atst-prod before_install: - # Use sed to replace the SSH URL with the public URL - - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules - # Manually initialize submodules - - git submodule update --init --recursive + # Use sed to replace the SSH URL with the public URL + - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules + # Manually initialize submodules + - git submodule update --init --recursive before_script: + - docker run -d --name postgres96 postgres:9.6-alpine + - docker run -d --name redis redis:4.0.10-alpine + - docker run --link postgres96:postgres96 --link redis:redis waisbrot/wait + - export postgres_ip="$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" postgres96)" + - export redis_ip="$(docker inspect -f "{{ .NetworkSettings.IPAddress }}" redis)" - docker login -u $ATAT_DOCKER_REGISTRY_USERNAME -p $ATAT_DOCKER_REGISTRY_PASSWORD $ATAT_DOCKER_REGISTRY_URL - - docker build --tag "${TESTER_IMAGE_NAME}" . -f deploy/docker/tester/Dockerfile + - docker build --tag "${TESTER_IMAGE_NAME}" --add-host "postgreshost:${postgres_ip}" --add-host "redishost:${redis_ip}" . -f deploy/docker/tester/Dockerfile script: - - docker run "${TESTER_IMAGE_NAME}" + - docker run --add-host "postgreshost:${postgres_ip}" --add-host "redishost:${redis_ip}" "${TESTER_IMAGE_NAME}" before_deploy: - docker build --tag "${PROD_IMAGE_NAME}" . -f deploy/docker/prod/Dockerfile diff --git a/Pipfile b/Pipfile index eb946fb9..1312960b 100644 --- a/Pipfile +++ b/Pipfile @@ -4,22 +4,31 @@ verify_ssl = true name = "pypi" [packages] -tornado = "==5.0.2" -webassets = "==0.12.1" -Unipath = "==1.1" -wtforms-tornado = "*" +webassets = "*" +Unipath = "*" pendulum = "*" redis = "*" +sqlalchemy = "*" +alembic = "*" +"psycopg2-binary" = "*" +flask = "*" +flask-sqlalchemy = "*" +flask-assets = "*" +flask-session = "*" +flask-wtf = "*" +pyopenssl = "*" +requests = "*" [dev-packages] bandit = "*" -pytest = "==3.6.0" -pytest-tornado = "==0.5.0" +pytest = "*" ipython = "*" ipdb = "*" pylint = "*" black = "*" pytest-watch = "*" +factory-boy = "*" +pytest-flask = "*" [requires] python_version = "3.6" diff --git a/Pipfile.lock b/Pipfile.lock index 2fadae1e..b9b8cab6 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "3bea02ccdb0e3877f2595d7fb405408114ec8947e0484d5b4aaf14a4c8ff78b2" + "sha256": "2b149e0d8c23814a2c701b53f5c75b36714a2ccd4e2a2769924ef6e2a3f09e97" }, "pipfile-spec": 6, "requires": { @@ -16,21 +16,242 @@ ] }, "default": { - "pendulum": { + "alembic": { "hashes": [ - "sha256:0643d45824e6789b88187728337dfa6075a0233f6976c2abefba00d064156309", - "sha256:3cc271195d8054bec06f54ff7d56ea6c2e2b5ad5dd6b532d787b34d2cabe6a65", - "sha256:544e44d8a92954e5ef4db4fa8b662d3282f2ac7b7c2cbf4227dc193ba78b9e1e", - "sha256:846478ab5f7480b3d850a09e44fe03830d448633c84f0b1066615ff6c34293aa", - "sha256:8bb523f759daeecfc0649369f198cbeb27a6608347354f4f847d21d579003db6", - "sha256:a449142063100f1b3c1119453c7569667c9ba79897305a1c50ca83a8c790f1e4", - "sha256:b7ff156b3d7cccbdeeb63465578d9a4e6f57d463f6ff6d4474254208d08f8353", - "sha256:d8822a592bbc16576c44ec4625bff9187ed9b649d47714e4905a55adc5b25339", - "sha256:dd45c7b349faab69714df9835cdf8bf8bce50bf6fc471419d3b23ba33e1915a5", - "sha256:fac088b637b5db5a047a0e89194d8c3c9e9e9ce1665089240003bb7c05b92536" + "sha256:52d73b1d750f1414fa90c25a08da47b87de1e4ad883935718a8f36396e19e78e", + "sha256:eb7db9b4510562ec37c91d00b00d95fde076c1030d3f661aea882eec532b3565" ], "index": "pypi", - "version": "==2.0.2" + "version": "==1.0.0" + }, + "asn1crypto": { + "hashes": [ + "sha256:2f1adbb7546ed199e3c90ef23ec95c5cf3585bac7d11fb7eb562a3fe89c64e87", + "sha256:9d5c20441baf0cb60a4ac34cc447c6c189024b6b4c6cd7877034f4965c464e49" + ], + "version": "==0.24.0" + }, + "certifi": { + "hashes": [ + "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", + "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + ], + "version": "==2018.4.16" + }, + "cffi": { + "hashes": [ + "sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743", + "sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef", + "sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50", + "sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f", + "sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30", + "sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93", + "sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257", + "sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b", + "sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3", + "sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e", + "sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc", + "sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04", + "sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6", + "sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359", + "sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596", + "sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b", + "sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd", + "sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95", + "sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5", + "sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e", + "sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6", + "sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca", + "sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31", + "sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1", + "sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2", + "sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085", + "sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801", + "sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4", + "sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184", + "sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917", + "sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f", + "sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb" + ], + "version": "==1.11.5" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "click": { + "hashes": [ + "sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", + "sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" + ], + "version": "==6.7" + }, + "cryptography": { + "hashes": [ + "sha256:21af753934f2f6d1a10fe8f4c0a64315af209ef6adeaee63ca349797d747d687", + "sha256:27bb401a20a838d6d0ea380f08c6ead3ccd8c9d8a0232dc9adcc0e4994576a66", + "sha256:29720c4253263cff9aea64585adbbe85013ba647f6e98367efff9db2d7193ded", + "sha256:2a35b7570d8f247889784010aac8b384fd2e4a47b33e15c4a60b45a7c1944120", + "sha256:42c531a6a354407f42ee07fda5c2c0dc822cf6d52744949c182f2b295fbd4183", + "sha256:5eb86f03f9c4f0ac2336ac5431271072ddf7ecc76b338e26366732cfac58aa19", + "sha256:67f7f57eae8dede577f3f7775957f5bec93edd6bdb6ce597bb5b28e1bdf3d4fb", + "sha256:6ec84edcbc966ae460560a51a90046503ff0b5b66157a9efc61515c68059f6c8", + "sha256:7ba834564daef87557e7fcd35c3c3183a4147b0b3a57314e53317360b9b201b3", + "sha256:7d7f084cbe1fdb82be5a0545062b59b1ad3637bc5a48612ac2eb428ff31b31ea", + "sha256:82409f5150e529d699e5c33fa8fd85e965104db03bc564f5f4b6a9199e591f7c", + "sha256:87d092a7c2a44e5f7414ab02fb4145723ebba411425e1a99773531dd4c0e9b8d", + "sha256:8c56ef989342e42b9fcaba7c74b446f0cc9bed546dd00034fa7ad66fc00307ef", + "sha256:9449f5d4d7c516a6118fa9210c4a00f34384cb1d2028672100ee0c6cce49d7f6", + "sha256:bc2301170986ad82d9349a91eb8884e0e191209c45f5541b16aa7c0cfb135978", + "sha256:c132bab45d4bd0fff1d3fe294d92b0a6eb8404e93337b3127bdec9f21de117e6", + "sha256:c3d945b7b577f07a477700f618f46cbc287af3a9222cd73035c6ef527ef2c363", + "sha256:cee18beb4c807b5c0b178f4fa2fae03cef9d51821a358c6890f8b23465b7e5d2", + "sha256:d01dfc5c2b3495184f683574e03c70022674ca9a7be88589c5aba130d835ea90" + ], + "version": "==2.3" + }, + "flask": { + "hashes": [ + "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", + "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" + ], + "index": "pypi", + "version": "==1.0.2" + }, + "flask-assets": { + "hashes": [ + "sha256:6031527b89fb3509d1581d932affa5a79dd348cfffb58d0aef99a43461d47847" + ], + "index": "pypi", + "version": "==0.12" + }, + "flask-session": { + "hashes": [ + "sha256:a31c27e0c3287f00c825b3d9625aba585f4df4cccedb1e7dd5a69a215881a731", + "sha256:b9b32126bfc52c3169089f2ed9a40e34b589527bda48b633428e07d39d9c8792" + ], + "index": "pypi", + "version": "==0.3.1" + }, + "flask-sqlalchemy": { + "hashes": [ + "sha256:3bc0fac969dd8c0ace01b32060f0c729565293302f0c4269beed154b46bec50b", + "sha256:5971b9852b5888655f11db634e87725a9031e170f37c0ce7851cf83497f56e53" + ], + "index": "pypi", + "version": "==2.3.2" + }, + "flask-wtf": { + "hashes": [ + "sha256:5d14d55cfd35f613d99ee7cba0fc3fbbe63ba02f544d349158c14ca15561cc36", + "sha256:d9a9e366b32dcbb98ef17228e76be15702cd2600675668bca23f63a7947fd5ac" + ], + "index": "pypi", + "version": "==0.14.2" + }, + "idna": { + "hashes": [ + "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e", + "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16" + ], + "version": "==2.7" + }, + "itsdangerous": { + "hashes": [ + "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" + ], + "version": "==0.24" + }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" + }, + "mako": { + "hashes": [ + "sha256:4e02fde57bd4abb5ec400181e4c314f56ac3e49ba4fb8b0d50bba18cb27d25ae" + ], + "version": "==1.0.7" + }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "version": "==1.0" + }, + "pendulum": { + "hashes": [ + "sha256:0ec5371949e147753661e1e98721273170638034dfceb578f29d69d93d3d474b", + "sha256:10ccdc8c6d004ba97883dd0f57503963ddf6cb83e849a16c4675ba18da657564", + "sha256:37bb54bcbb9d7fccd725f3fda69702e51ab3de9971b4c1c986505fbb3bc58bed", + "sha256:51803352e40778f914ff7af3494788b404260b415d9a9d607a8cf73e5e120994", + "sha256:5de295ca85761d9adf4020e6f3bed6eb933846ccf23b74e04b071f6d677f11a4", + "sha256:73f850265adcf0986fcc0af83ae9c8c5a7ca3c4a2525184110478a8bfd1a77b3", + "sha256:8fe289356322f6b0f4510082b4c412a1496a64054a37ae86b24411868a1901c6", + "sha256:c0401482dfa9fbd7005f2dfbf54ec61fd2c8130df37651ac2a3722d1f049ae4e", + "sha256:c358ee65ddb99c2b1bf301458e43ed09ff6d40465bcc9928265246912fad4d0f", + "sha256:d07962450e808556b3e6209a5830e2bbf8c7747129580c3b5b09e641f72617ab", + "sha256:dc05e6186c9c3b9969326aded9cba7a796744918581b25457f5148a5e3475d55", + "sha256:ee9466eea403e8e308c284d3055e285b97905a5ffb1566df0ef200b4f39c0f15", + "sha256:f7fa6220251a636112721e8158b9dd59018d818ec121047900934d80864eca62" + ], + "index": "pypi", + "version": "==2.0.3" + }, + "psycopg2-binary": { + "hashes": [ + "sha256:04afb59bbbd2eab3148e6816beddc74348078b8c02a1113ea7f7822f5be4afe3", + "sha256:098b18f4d8857a8f9b206d1dc54db56c2255d5d26458917e7bcad61ebfe4338f", + "sha256:0bf855d4a7083e20ead961fda4923887094eaeace0ab2d76eb4aa300f4bbf5bd", + "sha256:197dda3ffd02057820be83fe4d84529ea70bf39a9a4daee1d20ffc74eb3d042e", + "sha256:278ef63afb4b3d842b4609f2c05ffbfb76795cf6a184deeb8707cd5ed3c981a5", + "sha256:3cbf8c4fc8f22f0817220891cf405831559f4d4c12c4f73913730a2ea6c47a47", + "sha256:4305aed922c4d9d6163ab3a41d80b5a1cfab54917467da8168552c42cad84d32", + "sha256:47ee296f704fb8b2a616dec691cdcfd5fa0f11943955e88faa98cbd1dc3b3e3d", + "sha256:4a0e38cb30457e70580903367161173d4a7d1381eb2f2cfe4e69b7806623f484", + "sha256:4d6c294c6638a71cafb82a37f182f24321f1163b08b5d5ca076e11fe838a3086", + "sha256:4f3233c366500730f839f92833194fd8f9a5c4529c8cd8040aa162c3740de8e5", + "sha256:5221f5a3f4ca2ddf0d58e8b8a32ca50948be9a43351fda797eb4e72d7a7aa34d", + "sha256:5c6ca0b507540a11eaf9e77dee4f07c131c2ec80ca0cffa146671bf690bc1c02", + "sha256:789bd89d71d704db2b3d5e67d6d518b158985d791d3b2dec5ab85457cfc9677b", + "sha256:7b94d29239efeaa6a967f3b5971bd0518d2a24edd1511edbf4a2c8b815220d07", + "sha256:89bc65ef3301c74cf32db25334421ea6adbe8f65601ea45dcaaf095abed910bb", + "sha256:89d6d3a549f405c20c9ae4dc94d7ed2de2fa77427a470674490a622070732e62", + "sha256:97521704ac7127d7d8ba22877da3c7bf4a40366587d238ec679ff38e33177498", + "sha256:a395b62d5f44ff6f633231abe568e2203b8fabf9797cd6386aa92497df912d9a", + "sha256:a6d32c37f714c3f34158f3fa659f3a8f2658d5f53c4297d45579b9677cc4d852", + "sha256:a89ee5c26f72f2d0d74b991ce49e42ddeb4ac0dc2d8c06a0f2770a1ab48f4fe0", + "sha256:b4c8b0ef3608e59317bfc501df84a61e48b5445d45f24d0391a24802de5f2d84", + "sha256:b5fcf07140219a1f71e18486b8dc28e2e1b76a441c19374805c617aa6d9a9d55", + "sha256:b86f527f00956ecebad6ab3bb30e3a75fedf1160a8716978dd8ce7adddedd86f", + "sha256:be4c4aa22ba22f70de36c98b06480e2f1697972d49eb20d525f400d204a6d272", + "sha256:c2ac7aa1a144d4e0e613ac7286dae85671e99fe7a1353954d4905629c36b811c", + "sha256:de26ef4787b5e778e8223913a3e50368b44e7480f83c76df1f51d23bd21cea16", + "sha256:e70ebcfc5372dc7b699c0110454fc4263967f30c55454397e5769eb72c0eb0ce", + "sha256:eadbd32b6bc48b67b0457fccc94c86f7ccc8178ab839f684eb285bb592dc143e", + "sha256:ecbc6dfff6db06b8b72ae8a2f25ff20fbdcb83cb543811a08f7cb555042aa729" + ], + "index": "pypi", + "version": "==2.7.5" + }, + "pycparser": { + "hashes": [ + "sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226" + ], + "version": "==2.18" + }, + "pyopenssl": { + "hashes": [ + "sha256:26ff56a6b5ecaf3a2a59f132681e2a80afcc76b4f902f612f518f92c2a1bf854", + "sha256:6488f1423b00f73b7ad5167885312bb0ce410d3312eb212393795b53c8caa580" + ], + "index": "pypi", + "version": "==18.0.0" }, "python-dateutil": { "hashes": [ @@ -39,12 +260,17 @@ ], "version": "==2.7.3" }, + "python-editor": { + "hashes": [ + "sha256:a3c066acee22a1c94f63938341d4fb374e3fdd69366ed6603d7b24bed1efc565" + ], + "version": "==1.0.3" + }, "pytzdata": { "hashes": [ "sha256:1d936da41ee06216d89fdc7ead1ee9a5da2811a8787515a976b646e110c3f622", "sha256:e4ef42e82b0b493c5849eed98b5ab49d6767caf982127e9a33167f1153b36cc5" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", "version": "==2018.5" }, "redis": { @@ -55,6 +281,14 @@ "index": "pypi", "version": "==2.10.6" }, + "requests": { + "hashes": [ + "sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1", + "sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a" + ], + "index": "pypi", + "version": "==2.19.1" + }, "six": { "hashes": [ "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", @@ -62,16 +296,12 @@ ], "version": "==1.11.0" }, - "tornado": { + "sqlalchemy": { "hashes": [ - "sha256:1b83d5c10550f2653380b4c77331d6f8850f287c4f67d7ce1e1c639d9222fbc7", - "sha256:408d129e9d13d3c55aa73f8084aa97d5f90ed84132e38d6932e63a67d5bec563", - "sha256:88ce0282cce70df9045e515f578c78f1ebc35dcabe1d70f800c3583ebda7f5f5", - "sha256:ba9fbb249ac5390bff8a1d6aa4b844fd400701069bda7d2e380dfe2217895101", - "sha256:c050089173c2e9272244bccfb6a8615fb9e53b79420a5551acfa76094ecc3111" + "sha256:72325e67fb85f6e9ad304c603d83626d1df684fdf0c7ab1f0352e71feeab69d8" ], "index": "pypi", - "version": "==5.0.2" + "version": "==1.2.10" }, "unipath": { "hashes": [ @@ -81,6 +311,14 @@ "index": "pypi", "version": "==1.1" }, + "urllib3": { + "hashes": [ + "sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf", + "sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5" + ], + "markers": "python_version >= '2.6' and python_version != '3.1.*' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.3.*' and python_version < '4'", + "version": "==1.23" + }, "webassets": { "hashes": [ "sha256:e7d9c8887343123fd5b32309b33167428cb1318cdda97ece12d0907fd69d38db" @@ -88,19 +326,19 @@ "index": "pypi", "version": "==0.12.1" }, + "werkzeug": { + "hashes": [ + "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", + "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + ], + "version": "==0.14.1" + }, "wtforms": { "hashes": [ "sha256:0cdbac3e7f6878086c334aa25dc5a33869a3954e9d1e015130d65a69309b3b61", "sha256:e3ee092c827582c50877cdbd49e9ce6d2c5c1f6561f849b3b068c1b8029626f1" ], "version": "==2.2.1" - }, - "wtforms-tornado": { - "hashes": [ - "sha256:dadb5e504d01f14bf75900f592888bb402ada6b8f8235fe583359f562d351a3a" - ], - "index": "pypi", - "version": "==0.0.2" } }, "develop": { @@ -128,10 +366,10 @@ }, "astroid": { "hashes": [ - "sha256:a8d8c7fe34e34e868426b9bafce852c355a3951eef60bc831b2ed541558f8d37", - "sha256:e722228b5259ce8c7cbf75f3b0ee8b483cfbd4df01167474a84087d1aeade22c" + "sha256:a48b57ede295c3188ef5c84273bc2a8eadc46e4cbb001eae0d49fb5d1fabbb19", + "sha256:d066cdeec5faeb51a4be5010da612680653d844b57afd86a5c8315f2f801b4cc" ], - "version": "==2.0.0.dev4" + "version": "==2.0.2" }, "atomicwrites": { "hashes": [ @@ -197,19 +435,43 @@ ], "version": "==0.6.2" }, + "factory-boy": { + "hashes": [ + "sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca", + "sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f" + ], + "index": "pypi", + "version": "==2.11.1" + }, + "faker": { + "hashes": [ + "sha256:0e9a1227a3a0f3297a485715e72ee6eb77081b17b629367042b586e38c03c867", + "sha256:b4840807a94a3bad0217d6ed3f9b65a1cc6e1db1c99e1184673056ae2c0a4c4d" + ], + "markers": "python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7' and python_version != '3.0.*'", + "version": "==0.8.17" + }, + "flask": { + "hashes": [ + "sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", + "sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" + ], + "index": "pypi", + "version": "==1.0.2" + }, "gitdb2": { "hashes": [ - "sha256:b60e29d4533e5e25bb50b7678bbc187c8f6bcff1344b4f293b2ba55c85795f09", - "sha256:cf9a4b68e8c4da8d42e48728c944ff7af2d8c9db303ac1ab32eac37aa4194b0e" + "sha256:87783b7f4a8f6b71c7fe81d32179b3c8781c1a7d6fa0c69bff2f315b00aff4f8", + "sha256:bb4c85b8a58531c51373c89f92163b92f30f81369605a67cd52d1fc21246c044" ], - "version": "==2.0.3" + "version": "==2.0.4" }, "gitpython": { "hashes": [ - "sha256:1ec4c44846cf76a1e55769560673a97731849c9d05401e035e607495f10db959", - "sha256:b60b045cf64a321e5b620debb49890099fa6c7be6dfb7fb249027e5d34227301" + "sha256:563221e5a44369c6b79172f455584c9ebbb122a13368cc82cb4b5addff788f82", + "sha256:8237dc5bfd6f1366abeee5624111b9d6879393d84745a507de0fda86043b65a8" ], - "version": "==2.1.10" + "version": "==2.1.11" }, "ipdb": { "hashes": [ @@ -220,11 +482,11 @@ }, "ipython": { "hashes": [ - "sha256:a0c96853549b246991046f32d19db7140f5b1a644cc31f0dc1edc86713b7676f", - "sha256:eca537aa61592aca2fef4adea12af8e42f5c335004dfa80c78caf80e8b525e5c" + "sha256:007dcd929c14631f83daff35df0147ea51d1af420da303fd078343878bd5fb62", + "sha256:b0f2ef9eada4a68ef63ee10b6dde4f35c840035c50fd24265f8052c98947d5a4" ], "index": "pypi", - "version": "==6.4.0" + "version": "==6.5.0" }, "ipython-genutils": { "hashes": [ @@ -239,9 +501,14 @@ "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8", "sha256:ec9ef8f4a9bc6f71eec99e1806bfa2de401650d996c59330782b89a5555c1497" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", "version": "==4.3.4" }, + "itsdangerous": { + "hashes": [ + "sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" + ], + "version": "==0.24" + }, "jedi": { "hashes": [ "sha256:b409ed0f6913a701ed474a614a3bb46e6953639033e31f769ca7581da5bd1ec1", @@ -249,6 +516,13 @@ ], "version": "==0.12.1" }, + "jinja2": { + "hashes": [ + "sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", + "sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" + ], + "version": "==2.10" + }, "lazy-object-proxy": { "hashes": [ "sha256:0ce34342b419bd8f018e6666bfef729aec3edf62345a53b537a4dcc115746a33", @@ -283,6 +557,12 @@ ], "version": "==1.3.1" }, + "markupsafe": { + "hashes": [ + "sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" + ], + "version": "==1.0" + }, "mccabe": { "hashes": [ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", @@ -292,11 +572,11 @@ }, "more-itertools": { "hashes": [ - "sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8", - "sha256:6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3", - "sha256:a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0" + "sha256:c187a73da93e7a8acc0001572aebc7e3c69daf7bf6881a2cea10650bd4420092", + "sha256:c476b5d3a34e12d40130bc2f935028b5f636df8f372dc2c1c01dc19681b2039e", + "sha256:fcbfeaea0be121980e15bc97b3817b5202ca73d0eae185b4550cbfce2a3ebb3d" ], - "version": "==4.2.0" + "version": "==4.3.0" }, "parso": { "hashes": [ @@ -313,10 +593,10 @@ }, "pbr": { "hashes": [ - "sha256:4f2b11d95917af76e936811be8361b2b19616e5ef3b55956a429ec7864378e0c", - "sha256:e0f23b61ec42473723b2fec2f33fb12558ff221ee551962f01dd4de9053c2055" + "sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45", + "sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa" ], - "version": "==4.1.0" + "version": "==4.2.0" }, "pexpect": { "hashes": [ @@ -335,12 +615,10 @@ }, "pluggy": { "hashes": [ - "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", - "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", - "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" + "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", + "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", - "version": "==0.6.0" + "version": "==0.7.1" }, "prompt-toolkit": { "hashes": [ @@ -362,7 +640,6 @@ "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" ], - "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.1.*' and python_version != '3.0.*'", "version": "==1.5.4" }, "pygments": { @@ -374,27 +651,27 @@ }, "pylint": { "hashes": [ - "sha256:285c9ae7255acb584057fe31051a37498985e632b99fc0ec93b7eb38a1b137f9", - "sha256:dd5c0fc4e6a4cb9483a4367699099a7dfc8a13de9ecac4cb16855ffac68d49de" + "sha256:1d6d3622c94b4887115fe5204982eee66fdd8a951cf98635ee5caee6ec98c3ec", + "sha256:31142f764d2a7cd41df5196f9933b12b7ee55e73ef12204b648ad7e556c119fb" ], "index": "pypi", - "version": "==2.0.0.dev2" + "version": "==2.1.1" }, "pytest": { "hashes": [ - "sha256:39555d023af3200d004d09e51b4dd9fdd828baa863cded3fd6ba2f29f757ae2d", - "sha256:c76e93f3145a44812955e8d46cdd302d8a45fbfc7bf22be24fe231f9d8d8853a" + "sha256:86a8dbf407e437351cef4dba46736e9c5a6e3c3ac71b2e942209748e76ff2086", + "sha256:e74466e97ac14582a8188ff4c53e6cc3810315f342f6096899332ae864c1d432" ], "index": "pypi", - "version": "==3.6.0" + "version": "==3.7.1" }, - "pytest-tornado": { + "pytest-flask": { "hashes": [ - "sha256:214fc59d06fb81696fce3028b56dff522168ac1cfc784cfc0077b7b1e425b4cd", - "sha256:687c1f9c0f5bda7808c1e53c14bbebfe4fb9452e34cc95b440e598d4724265e0" + "sha256:2c5a36f9033ef8b6f85ddbefaebdd4f89197fc283f94b20dfe1a1beba4b77f03", + "sha256:657c7de386215ab0230bee4d76ace0339ae82fcbb34e134e17a29f65032eef03" ], "index": "pypi", - "version": "==0.5.0" + "version": "==0.10.0" }, "pytest-watch": { "hashes": [ @@ -403,13 +680,24 @@ "index": "pypi", "version": "==4.2.0" }, + "python-dateutil": { + "hashes": [ + "sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0", + "sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8" + ], + "version": "==2.7.3" + }, "pyyaml": { "hashes": [ + "sha256:1cbc199009e78f92d9edf554be4fe40fb7b0bef71ba688602a00e97a51909110", "sha256:254bf6fda2b7c651837acb2c718e213df29d531eebf00edb54743d10bcb694eb", "sha256:3108529b78577327d15eec243f0ff348a0640b0c3478d67ad7f5648f93bac3e2", "sha256:3c17fb92c8ba2f525e4b5f7941d850e7a48c3a59b32d331e2502a3cdc6648e76", + "sha256:6f89b5c95e93945b597776163403d47af72d243f366bf4622ff08bdfd1c950b7", "sha256:8d6d96001aa7f0a6a4a95e8143225b5d06e41b1131044913fecb8f85a125714b", - "sha256:c8a88edd93ee29ede719080b2be6cb2333dfee1dccba213b422a9c8e97f2967b" + "sha256:be622cc81696e24d0836ba71f6272a2b5767669b0d79fdcf0295d51ac2e156c8", + "sha256:c8a88edd93ee29ede719080b2be6cb2333dfee1dccba213b422a9c8e97f2967b", + "sha256:f39411e380e2182ad33be039e8ee5770a5d9efe01a2bfb7ae58d9ba31c4a2a9d" ], "version": "==4.2b4" }, @@ -428,17 +716,24 @@ }, "smmap2": { "hashes": [ - "sha256:b78ee0f1f5772d69ff50b1cbdb01b8c6647a8354f02f23b488cf4b2cfc923956", - "sha256:c7530db63f15f09f8251094b22091298e82bf6c699a6b8344aaaef3f2e1276c3" + "sha256:0dd53d991af487f9b22774fa89451358da3607c02b9b886a54736c6a313ece0b", + "sha256:dc216005e529d57007ace27048eb336dcecb7fc413cfb3b2f402bb25972b69c6" ], - "version": "==2.0.3" + "version": "==2.0.4" }, "stevedore": { "hashes": [ - "sha256:e3d96b2c4e882ec0c1ff95eaebf7b575a779fd0ccb4c741b9832bed410d58b3d", - "sha256:f1c7518e7b160336040fee272174f1f7b29a46febb3632502a8f2055f973d60b" + "sha256:1e153545aca7a6a49d8337acca4f41c212fbfa60bf864ecd056df0cafb9627e8", + "sha256:c7eac1c0d95824c88b655273da5c17cdde6482b2739f47c30bf851dcc9d3c2c0" ], - "version": "==1.28.0" + "version": "==1.29.0" + }, + "text-unidecode": { + "hashes": [ + "sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d", + "sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc" + ], + "version": "==1.2" }, "toml": { "hashes": [ @@ -446,17 +741,6 @@ ], "version": "==0.9.4" }, - "tornado": { - "hashes": [ - "sha256:1b83d5c10550f2653380b4c77331d6f8850f287c4f67d7ce1e1c639d9222fbc7", - "sha256:408d129e9d13d3c55aa73f8084aa97d5f90ed84132e38d6932e63a67d5bec563", - "sha256:88ce0282cce70df9045e515f578c78f1ebc35dcabe1d70f800c3583ebda7f5f5", - "sha256:ba9fbb249ac5390bff8a1d6aa4b844fd400701069bda7d2e380dfe2217895101", - "sha256:c050089173c2e9272244bccfb6a8615fb9e53b79420a5551acfa76094ecc3111" - ], - "index": "pypi", - "version": "==5.0.2" - }, "traitlets": { "hashes": [ "sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835", @@ -490,9 +774,16 @@ "sha256:edb04bdd45bfd76c8292c4d9654568efaedf76fe78eb246dde69bdb13b2dad87", "sha256:f19f2a4f547505fe9072e15f6f4ae714af51b5a681a97f187971f50c283193b6" ], - "markers": "python_version < '3.7' and implementation_name == 'cpython'", "version": "==1.1.0" }, + "typing": { + "hashes": [ + "sha256:3a887b021a77b292e151afb75323dea88a7bc1b3dfa92176cff8e44c8b68bddf", + "sha256:b2c689d54e1144bbcfd191b0832980a21c2dbcf7b5ff7a66248a60c90e951eb8", + "sha256:d400a9344254803a2368533e4533a4200d21eb7b6b729c173bc38201a74db3f2" + ], + "version": "==3.6.4" + }, "watchdog": { "hashes": [ "sha256:7e65882adb7746039b6f3876ee174952f8eaaa34491ba34333ddf1fe35de4162" @@ -506,6 +797,13 @@ ], "version": "==0.1.7" }, + "werkzeug": { + "hashes": [ + "sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", + "sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" + ], + "version": "==0.14.1" + }, "wrapt": { "hashes": [ "sha256:d4d560d479f2c21e1b5443bbd15fe7ec4b37fe7e53d335d3b9b0a7b1226fe3c6" diff --git a/README.md b/README.md index 6089986f..e07d91ea 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,22 @@ - # ATST [![Build Status](https://travis-ci.org/dod-ccpo/atst.svg?branch=master)](https://travis-ci.org/dod-ccpo/atst) ## Description -This is the main user-facing web application for the ATAT stack. All end-user -requests are handled by ATST, with it making backend calls to various -microservices when appropriate. +This is the user-facing web application for ATAT. ## Installation ### Requirements See the [scriptz](https://github.com/dod-ccpo/scriptz) repository for the shared requirements and guidelines for all ATAT applications. -Additionally, ATST requires a redis instance for session management. Have redis -installed and running. By default, ATST will try to connect to a redis instance -running on localhost on its default port, 6379. + +ATST requires a postgres instance (>= 9.6) for persistence. Have postgres installed +and running on the default port of 5432. + +ATST also requires a redis instance for session management. Have redis installed and +running on the default port of 6379. ### Cloning This project contains git submodules. Here is an example clone command that will @@ -58,6 +58,10 @@ To start the app locally in the foreground and watch for changes: script/dev_server +To watch for changes to any js/css assets: + + yarn watch + ### Users There are currently six mock users for development: @@ -73,6 +77,12 @@ To log in as one of them, navigate to `/login-dev?username=`. Fo ## Testing +Tests require a test database: + +``` +createdb atat_test +``` + To run lint, static analysis, and unit tests: script/test @@ -87,14 +97,21 @@ To re-run tests each time a file is changed: ## Notes -tornado templates are like mustache templates -- add the +Jinja templates are like mustache templates -- add the following to `~/.vim/filetype.vim` for syntax highlighting: :au BufRead *.html.to set filetype=mustache ## Icons -To render an icon use `{% module Icon('name') %}` in a template, where `name` is the filename of an svg file in `static/icons`. +To render an icon, use + +```jinja +{% import "components/icon.html" %} +{{ Icon("icon-name", classes="css-classes") }} +``` + +where `icon-name` is the filename of an svg in `static/icons`. All icons used should be from the Noun Project, specifically [this collection](https://thenounproject.com/monstercritic/collection/tinicons-a-set-of-tiny-icons-perfect-for-ui-elemen/) if possible. @@ -104,7 +121,7 @@ SVG markup should be cleaned an minified, [Svgsus](http://www.svgs.us/) works we The `/login-dev` endpoint is protected by HTTP basic auth when deployed. This can be configured for NGINX following the instructions [here](https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/). The following config should added within the main server block for the site: -``` +```nginx location /login-dev { auth_basic "Developer Access"; auth_basic_user_file /etc/apache2/.htpasswd; diff --git a/alembic.ini b/alembic.ini new file mode 100644 index 00000000..08ce3124 --- /dev/null +++ b/alembic.ini @@ -0,0 +1,74 @@ +# A generic, single database configuration. + +[alembic] +# path to migration scripts +script_location = alembic + +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# timezone to use when rendering the date +# within the migration file as well as the filename. +# string value is passed to dateutil.tz.gettz() +# leave blank for localtime +# timezone = + +# max length of characters to apply to the +# "slug" field +#truncate_slug_length = 40 + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + +# set to 'true' to allow .pyc and .pyo files without +# a source .py file to be detected as revisions in the +# versions/ directory +# sourceless = false + +# version location specification; this defaults +# to alembic/versions. When using multiple version +# directories, initial revisions must be specified with --version-path +# version_locations = %(here)s/bar %(here)s/bat alembic/versions + +# the output encoding used when revision files +# are written from script.py.mako +# output_encoding = utf-8 + +sqlalchemy.url = driver://user:pass@localhost/dbname + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/alembic/README b/alembic/README new file mode 100644 index 00000000..98e4f9c4 --- /dev/null +++ b/alembic/README @@ -0,0 +1 @@ +Generic single-database configuration. \ No newline at end of file diff --git a/alembic/env.py b/alembic/env.py new file mode 100644 index 00000000..91b96364 --- /dev/null +++ b/alembic/env.py @@ -0,0 +1,84 @@ +from __future__ import with_statement +from alembic import context +from sqlalchemy import engine_from_config, pool +from logging.config import fileConfig + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +target_metadata = None + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + +import sys +from unipath import Path + +parent_dir = Path(__file__).parent.parent +sys.path.append(parent_dir) + +from atst.app import make_config +app_config = make_config() +config.set_main_option('sqlalchemy.url', app_config['DATABASE_URI']) + +from atst.database import db +from atst.models import * +target_metadata = Base.metadata + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=target_metadata, literal_binds=True) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + connectable = engine_from_config( + config.get_section(config.config_ini_section), + prefix='sqlalchemy.', + poolclass=pool.NullPool) + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=target_metadata + ) + + with context.begin_transaction(): + context.run_migrations() + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/alembic/script.py.mako b/alembic/script.py.mako new file mode 100644 index 00000000..2c015630 --- /dev/null +++ b/alembic/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/alembic/versions/1f57f784ed5b_update_user_from_authnid.py b/alembic/versions/1f57f784ed5b_update_user_from_authnid.py new file mode 100644 index 00000000..56928d6a --- /dev/null +++ b/alembic/versions/1f57f784ed5b_update_user_from_authnid.py @@ -0,0 +1,38 @@ +"""update_user_from_authnid + +Revision ID: 1f57f784ed5b +Revises: 55ba973d08b9 +Create Date: 2018-07-30 16:53:05.945005 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '1f57f784ed5b' +down_revision = '55ba973d08b9' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('users', sa.Column('dod_id', sa.String(), nullable=True)) + op.add_column('users', sa.Column('email', sa.String(), nullable=True)) + op.add_column('users', sa.Column('first_name', sa.String(), nullable=True)) + op.add_column('users', sa.Column('last_name', sa.String(), nullable=True)) + op.create_unique_constraint('users_dod_id_unique', 'users', ['dod_id']) + op.create_unique_constraint('users_email_unqiue', 'users', ['email']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('users_dod_id_unique', 'users', type_='unique') + op.drop_constraint('users_email_unqiue', 'users', type_='unique') + op.drop_column('users', 'last_name') + op.drop_column('users', 'first_name') + op.drop_column('users', 'email') + op.drop_column('users', 'dod_id') + # ### end Alembic commands ### diff --git a/alembic/versions/4ea5917e7781_add_default_atat_role.py b/alembic/versions/4ea5917e7781_add_default_atat_role.py new file mode 100644 index 00000000..78b6ef55 --- /dev/null +++ b/alembic/versions/4ea5917e7781_add_default_atat_role.py @@ -0,0 +1,39 @@ +"""add_default_atat_role + +Revision ID: 4ea5917e7781 +Revises: 96a9f3537996 +Create Date: 2018-07-30 13:51:29.576931 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.orm.session import Session + + +# revision identifiers, used by Alembic. +revision = '4ea5917e7781' +down_revision = '96a9f3537996' +branch_labels = None +depends_on = None + +from atst.models.role import Role +from atst.models.permissions import Permissions + + +def upgrade(): + session = Session(bind=op.get_bind()) + mission_owner_role = Role( + name='default', + description='', + permissions=[ + Permissions.REQUEST_JEDI_WORKSPACE, + ] + ) + session.add(mission_owner_role) + session.commit() + + +def downgrade(): + db = op.get_bind() + db.execute("DELETE FROM roles WHERE name = 'default'") + diff --git a/alembic/versions/4ede1e3e50d1_add_authz_models.py b/alembic/versions/4ede1e3e50d1_add_authz_models.py new file mode 100644 index 00000000..d782b676 --- /dev/null +++ b/alembic/versions/4ede1e3e50d1_add_authz_models.py @@ -0,0 +1,62 @@ +"""add_authz_models + +Revision ID: 4ede1e3e50d1 +Revises: b5b17d465166 +Create Date: 2018-07-30 11:34:12.016857 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '4ede1e3e50d1' +down_revision = 'b5b17d465166' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('roles', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('name', sa.String(), nullable=True), + sa.Column('description', sa.String(), nullable=True), + sa.Column('permissions', postgresql.ARRAY(sa.String()), server_default='{}', nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_roles_name'), 'roles', ['name'], unique=True) + op.create_index(op.f('ix_roles_permissions'), 'roles', ['permissions'], unique=False) + op.create_table('users', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('username', sa.String(), nullable=True), + sa.Column('atat_role_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.ForeignKeyConstraint(['atat_role_id'], ['roles.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('workspace_role', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('workspace_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('role_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.create_index(op.f('ix_workspace_role_user_id'), 'workspace_role', ['user_id'], unique=False) + op.create_index(op.f('ix_workspace_role_workspace_id'), 'workspace_role', ['workspace_id'], unique=False) + op.create_index('workspace_role_user_workspace', 'workspace_role', ['user_id', 'workspace_id'], unique=True) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('workspace_role_user_workspace', table_name='workspace_role') + op.drop_index(op.f('ix_workspace_role_workspace_id'), table_name='workspace_role') + op.drop_index(op.f('ix_workspace_role_user_id'), table_name='workspace_role') + op.drop_table('workspace_role') + op.drop_table('users') + op.drop_index(op.f('ix_roles_permissions'), table_name='roles') + op.drop_index(op.f('ix_roles_name'), table_name='roles') + op.drop_table('roles') + # ### end Alembic commands ### diff --git a/alembic/versions/55ba973d08b9_add_fundz_models.py b/alembic/versions/55ba973d08b9_add_fundz_models.py new file mode 100644 index 00000000..097532f4 --- /dev/null +++ b/alembic/versions/55ba973d08b9_add_fundz_models.py @@ -0,0 +1,38 @@ +"""add_fundz_models + +Revision ID: 55ba973d08b9 +Revises: 4ea5917e7781 +Create Date: 2018-07-30 14:43:34.099799 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '55ba973d08b9' +down_revision = '4ea5917e7781' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('pe_number', + sa.Column('number', sa.String(), nullable=False), + sa.Column('description', sa.String(), nullable=True), + sa.PrimaryKeyConstraint('number') + ) + op.create_table('task_order', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('number', sa.String(), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('task_order') + op.drop_table('pe_number') + # ### end Alembic commands ### diff --git a/alembic/versions/96a9f3537996_add_roles_and_permissions.py b/alembic/versions/96a9f3537996_add_roles_and_permissions.py new file mode 100644 index 00000000..4380208a --- /dev/null +++ b/alembic/versions/96a9f3537996_add_roles_and_permissions.py @@ -0,0 +1,183 @@ +"""add_roles_and_permissions + +Revision ID: 96a9f3537996 +Revises: 4ede1e3e50d1 +Create Date: 2018-07-30 13:48:31.325234 + +""" +import os +import sys +from alembic import op +import sqlalchemy as sa + +from sqlalchemy.orm.session import Session + +from atst.models.role import Role +from atst.models.permissions import Permissions + +# revision identifiers, used by Alembic. +revision = '96a9f3537996' +down_revision = '4ede1e3e50d1' +branch_labels = None +depends_on = None + + +def upgrade(): + session = Session(bind=op.get_bind()) + roles = [ + Role( + name='ccpo', + description='', + permissions=[ + Permissions.VIEW_ORIGINAL_JEDI_REQEUST, + Permissions.REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST, + Permissions.MODIFY_ATAT_ROLE_PERMISSIONS, + Permissions.CREATE_CSP_ROLE, + Permissions.DELETE_CSP_ROLE, + Permissions.DEACTIVE_CSP_ROLE, + Permissions.MODIFY_CSP_ROLE_PERMISSIONS, + + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + Permissions.ADD_AND_ASSIGN_CSP_ROLES, + Permissions.REMOVE_CSP_ROLES, + Permissions.REQUEST_NEW_CSP_ROLE, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.DEACTIVATE_WORKSPACE, + Permissions.VIEW_ATAT_PERMISSIONS, + Permissions.TRANSFER_OWNERSHIP_OF_WORKSPACE, + + Permissions.ADD_APPLICATION_IN_WORKSPACE, + Permissions.DELETE_APPLICATION_IN_WORKSPACE, + Permissions.DEACTIVATE_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.RENAME_APPLICATION_IN_WORKSPACE, + + Permissions.ADD_ENVIRONMENT_IN_APPLICATION, + Permissions.DELETE_ENVIRONMENT_IN_APPLICATION, + Permissions.DEACTIVATE_ENVIRONMENT_IN_APPLICATION, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + Permissions.RENAME_ENVIRONMENT_IN_APPLICATION, + + Permissions.ADD_TAG_TO_WORKSPACE, + Permissions.REMOVE_TAG_FROM_WORKSPACE + ] + ), + Role( + name='owner', + description='', + permissions=[ + Permissions.REQUEST_JEDI_WORKSPACE, + Permissions.VIEW_ORIGINAL_JEDI_REQEUST, + + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + Permissions.ADD_AND_ASSIGN_CSP_ROLES, + Permissions.REMOVE_CSP_ROLES, + Permissions.REQUEST_NEW_CSP_ROLE, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.DEACTIVATE_WORKSPACE, + Permissions.VIEW_ATAT_PERMISSIONS, + + Permissions.ADD_APPLICATION_IN_WORKSPACE, + Permissions.DELETE_APPLICATION_IN_WORKSPACE, + Permissions.DEACTIVATE_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.RENAME_APPLICATION_IN_WORKSPACE, + + Permissions.ADD_ENVIRONMENT_IN_APPLICATION, + Permissions.DELETE_ENVIRONMENT_IN_APPLICATION, + Permissions.DEACTIVATE_ENVIRONMENT_IN_APPLICATION, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + Permissions.RENAME_ENVIRONMENT_IN_APPLICATION, + ] + ), + Role( + name='admin', + description='', + permissions=[ + Permissions.VIEW_USAGE_REPORT, + Permissions.ADD_AND_ASSIGN_CSP_ROLES, + Permissions.REMOVE_CSP_ROLES, + Permissions.REQUEST_NEW_CSP_ROLE, + Permissions.ASSIGN_AND_UNASSIGN_ATAT_ROLE, + + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.ADD_APPLICATION_IN_WORKSPACE, + Permissions.DELETE_APPLICATION_IN_WORKSPACE, + Permissions.DEACTIVATE_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.RENAME_APPLICATION_IN_WORKSPACE, + + Permissions.ADD_ENVIRONMENT_IN_APPLICATION, + Permissions.DELETE_ENVIRONMENT_IN_APPLICATION, + Permissions.DEACTIVATE_ENVIRONMENT_IN_APPLICATION, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + Permissions.RENAME_ENVIRONMENT_IN_APPLICATION, + ] + ), + Role( + name='developer', + description='', + permissions=[ + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION + ] + ), + Role( + name='billing_auditor', + description='', + permissions=[ + Permissions.VIEW_USAGE_REPORT, + Permissions.VIEW_USAGE_DOLLARS, + + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + ] + ), + Role( + name='security_auditor', + description='', + permissions=[ + Permissions.VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS, + Permissions.VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS, + + Permissions.VIEW_ATAT_PERMISSIONS, + + Permissions.VIEW_APPLICATION_IN_WORKSPACE, + + Permissions.VIEW_ENVIRONMENT_IN_APPLICATION, + ] + ), + ] + + session.add_all(roles) + session.commit() + + +def downgrade(): + db = op.get_bind() + db.execute(""" + DELETE FROM roles + WHERE name IN ( + 'ccpo', + 'owner', + 'admin', + 'developer', + 'billing_auditor', + 'security_auditor' + ); + """) diff --git a/alembic/versions/b5b17d465166_requests.py b/alembic/versions/b5b17d465166_requests.py new file mode 100644 index 00000000..b8d47c06 --- /dev/null +++ b/alembic/versions/b5b17d465166_requests.py @@ -0,0 +1,47 @@ +"""requests + +Revision ID: b5b17d465166 +Revises: ff1c9c02fa61 +Create Date: 2018-07-23 14:58:05.044456 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'b5b17d465166' +down_revision = 'ff1c9c02fa61' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('requests', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('creator', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('time_created', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('body', postgresql.JSONB(astext_type=sa.Text()), nullable=True), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('request_status_events', + sa.Column('id', postgresql.UUID(as_uuid=True), server_default=sa.text('uuid_generate_v4()'), nullable=False), + sa.Column('new_status', sa.String(), nullable=True), + sa.Column('time_created', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=True), + sa.Column('request_id', postgresql.UUID(as_uuid=True), nullable=True), + sa.Column('sequence', sa.BigInteger(), nullable=False), + sa.ForeignKeyConstraint(['request_id'], ['requests.id'], ondelete='CASCADE'), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + db = op.get_bind() + db.execute("CREATE SEQUENCE request_status_events_sequence_seq OWNED BY request_status_events.sequence;") + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('request_status_events') + op.drop_table('requests') + # ### end Alembic commands ### diff --git a/alembic/versions/ff1c9c02fa61_enable_uuid_extension.py b/alembic/versions/ff1c9c02fa61_enable_uuid_extension.py new file mode 100644 index 00000000..a6f6206a --- /dev/null +++ b/alembic/versions/ff1c9c02fa61_enable_uuid_extension.py @@ -0,0 +1,26 @@ +"""enable uuid extension + +Revision ID: ff1c9c02fa61 +Revises: +Create Date: 2018-07-23 14:54:05.422286 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ff1c9c02fa61' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + connection = op.get_bind() + connection.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"') + + +def downgrade(): + connection = op.get_bind() + connection.execute('DROP EXTENSION IF EXISTS "uuid-ossp"') diff --git a/app.py b/app.py index b6d66f53..6d786f34 100755 --- a/app.py +++ b/app.py @@ -1,15 +1,11 @@ #!/usr/bin/env python -import tornado.ioloop - -from atst.app import make_app, make_deps, make_config +from atst.app import make_app, make_config config = make_config() -deps = make_deps(config) -app = make_app(config, deps) +app = make_app(config) if __name__ == "__main__": - port = int(config["default"]["PORT"]) - app.listen(port) + port = int(config["PORT"]) + app.run(port=port) print("Listening on http://localhost:%i" % port) - tornado.ioloop.IOLoop.current().start() diff --git a/atst/api_client.py b/atst/api_client.py deleted file mode 100644 index c41e0682..00000000 --- a/atst/api_client.py +++ /dev/null @@ -1,60 +0,0 @@ -import tornado.gen -from tornado.httpclient import AsyncHTTPClient -from json import dumps, loads, decoder - - -class ApiClient(object): - def __init__(self, base_url, api_version=None, validate_cert=True): - self.base_url = base_url - if api_version: - self.base_url = f"{base_url}/api/{api_version}" - self.client = AsyncHTTPClient() - self.validate_cert = validate_cert - - @tornado.gen.coroutine - def get(self, path, **kwargs): - return (yield self.make_request("GET", self.base_url + path, **kwargs)) - - @tornado.gen.coroutine - def put(self, path, **kwargs): - return (yield self.make_request("PUT", self.base_url + path, **kwargs)) - - @tornado.gen.coroutine - def post(self, path, **kwargs): - return (yield self.make_request("POST", self.base_url + path, **kwargs)) - - @tornado.gen.coroutine - def patch(self, path, **kwargs): - return (yield self.make_request("PATCH", self.base_url + path, **kwargs)) - - @tornado.gen.coroutine - def delete(self, path, **kwargs): - return (yield self.make_request("DELETE", self.base_url + path, **kwargs)) - - @tornado.gen.coroutine - def make_request(self, method, url, **kwargs): - # If 'json' kwarg is specified, serialize it to 'body' and update - # the Content-Type. - if "json" in kwargs: - kwargs["body"] = dumps(kwargs["json"]) - del kwargs["json"] - headers = kwargs.get("headers", {}) - headers["Content-Type"] = "application/json" - kwargs["headers"] = headers - if not "validate_cert" in kwargs: - kwargs["validate_cert"] = self.validate_cert - - response = yield self.client.fetch(url, method=method, **kwargs) - return self.adapt_response(response) - - def adapt_response(self, response): - if "application/json" in response.headers["Content-Type"]: - try: - json = loads(response.body) - setattr(response, "json", json) - except decoder.JSONDecodeError: - setattr(response, "json", {}) - else: - setattr(response, "json", {}) - setattr(response, "ok", 200 <= response.code < 300) - return response diff --git a/atst/app.py b/atst/app.py index aa101838..4b7a0806 100644 --- a/atst/app.py +++ b/atst/app.py @@ -1,187 +1,96 @@ import os +import re +import pathlib from configparser import ConfigParser -import tornado.web -from tornado.web import url -from redis import StrictRedis +from flask import Flask, request, g +from flask_session import Session +import redis +from unipath import Path +from flask_wtf.csrf import CSRFProtect -from atst.handlers.main import Main -from atst.handlers.root import Root -from atst.handlers.login_redirect import LoginRedirect -from atst.handlers.workspaces import Workspaces -from atst.handlers.workspace import Workspace -from atst.handlers.workspace_members import WorkspaceMembers -from atst.handlers.request import Request -from atst.handlers.request_financial_verification import RequestFinancialVerification -from atst.handlers.request_new import RequestNew -from atst.handlers.request_submit import RequestsSubmit -from atst.handlers.dev import Dev -from atst.home import home -from atst.api_client import ApiClient -from atst.sessions import RedisSessions -from atst import ui_modules -from atst import ui_methods +from atst.database import db +from atst.assets import environment as assets_environment -ENV = os.getenv("TORNADO_ENV", "dev") +from atst.routes import bp +from atst.routes.workspaces import bp as workspace_routes +from atst.routes.requests import requests_bp +from atst.routes.dev import bp as dev_routes +from atst.domain.authnid.crl.validator import Validator +from atst.domain.auth import apply_authentication -def make_app(config, deps, **kwargs): - routes = [ - url(r"/", Root, {"page": "root"}, name="root"), - url( - r"/login-redirect", - LoginRedirect, - {"sessions": deps["sessions"], "authnid_client": deps["authnid_client"], "authz_client": deps["authz_client"]}, - name="login_redirect", - ), - url(r"/home", Main, {"page": "home"}, name="home"), - url( - r"/styleguide", - Main, - {"page": "styleguide"}, - name="styleguide", - ), - url( - r"/workspaces/blank", - Main, - {"page": "workspaces_blank"}, - name="workspaces_blank", - ), - url( - r"/workspaces", - Workspaces, - {"page": "workspaces", "authz_client": deps["authz_client"]}, - name="workspaces", - ), - url( - r"/requests", - Request, - {"page": "requests", "requests_client": deps["requests_client"]}, - name="requests", - ), - url( - r"/requests/new", - RequestNew, - { - "page": "requests_new", - "requests_client": deps["requests_client"], - "fundz_client": deps["fundz_client"], - }, - name="request_new", - ), - url( - r"/requests/new/([0-9])", - RequestNew, - { - "page": "requests_new", - "requests_client": deps["requests_client"], - "fundz_client": deps["fundz_client"], - }, - name="request_form_new", - ), - url( - r"/requests/new/([0-9])/(\S+)", - RequestNew, - { - "page": "requests_new", - "requests_client": deps["requests_client"], - "fundz_client": deps["fundz_client"], - }, - name="request_form_update", - ), - url( - r"/requests/submit/(\S+)", - RequestsSubmit, - {"requests_client": deps["requests_client"]}, - name="requests_submit", - ), - # Dummy request/approval screen - url( - r"/request/approval", - Main, - {"page": "request_approval"}, - name="request_approval" - ), - url( - r"/requests/verify/(\S+)", - RequestFinancialVerification, - { - "page": "financial_verification", - "requests_client": deps["requests_client"], - "fundz_client": deps["fundz_client"], - }, - name="financial_verification", - ), - url( - r"/requests/financial_verification_submitted", - Main, - {"page": "requests/financial_verification_submitted"}, - name="financial_verification_submitted", - ), - url(r"/users", Main, {"page": "users"}, name="users"), - url(r"/reports", Main, {"page": "reports"}, name="reports"), - url(r"/calculator", Main, {"page": "calculator"}, name="calculator"), - url(r"/workspaces/(\S+)/members", WorkspaceMembers, {}, name="workspace_members"), - url(r"/workspaces/(\S+)/projects", Workspace, {}, name="workspace_projects"), - url(r"/workspaces/123456/projects/789/edit", Main, {"page": "project_edit"}, name="project_edit"), - url(r"/workspaces/123456/members/789/edit", Main, {"page": "member_edit"}, name="member_edit"), - ] +ENV = os.getenv("FLASK_ENV", "dev") - if not ENV == "production": - routes += [ - url( - r"/login-dev", - Dev, - {"action": "login", "sessions": deps["sessions"], "authz_client": deps["authz_client"]}, - name="dev-login", - ) - ] - app = tornado.web.Application( - routes, - login_url="/", - template_path=home.child("templates"), - static_path=home.child("static"), - cookie_secret=config["default"]["COOKIE_SECRET"], - debug=config["default"].getboolean("DEBUG"), - ui_modules=ui_modules, - ui_methods=ui_methods, - **kwargs, +def make_app(config): + + parent_dir = Path().parent + + app = Flask( + __name__, + template_folder=parent_dir.child("templates").absolute(), + static_folder=parent_dir.child("static").absolute(), ) - app.config = config - app.sessions = deps["sessions"] + redis = make_redis(config) + csrf = CSRFProtect() + + app.config.update(config) + app.config.update({"SESSION_REDIS": redis}) + + make_flask_callbacks(app) + make_crl_validator(app) + + db.init_app(app) + csrf.init_app(app) + Session(app) + assets_environment.init_app(app) + + app.register_blueprint(bp) + app.register_blueprint(workspace_routes) + app.register_blueprint(requests_bp) + if ENV != "production": + app.register_blueprint(dev_routes) + + apply_authentication(app) + return app -def make_deps(config): - # we do not want to do SSL verify services in test and development - validate_cert = ENV == "production" - redis_client = StrictRedis.from_url( - config["default"]["REDIS_URI"], decode_responses=True - ) +def make_flask_callbacks(app): + @app.before_request + def _set_globals(): + g.navigationContext = ( + "workspace" + if re.match("\/workspaces\/[A-Za-z0-9]*", request.url) + else "global" + ) + g.dev = os.getenv("FLASK_ENV", "dev") == "dev" + g.matchesPath = lambda href: re.match("^" + href, request.path) + g.modalOpen = request.args.get("modal", False) + g.current_user = { + "id": "cce17030-4109-4719-b958-ed109dbb87c8", + "first_name": "Amanda", + "last_name": "Adamson", + "atat_role": "default", + "atat_permissions": [], + } + @app.template_filter('iconSvg') + def _iconSvg(name): + with open('static/icons/'+name+'.svg') as contents: + return contents.read() + + +def map_config(config): return { - "authz_client": ApiClient( - config["default"]["AUTHZ_BASE_URL"], - api_version="v1", - validate_cert=validate_cert, - ), - "authnid_client": ApiClient( - config["default"]["AUTHNID_BASE_URL"], - api_version="v1", - validate_cert=validate_cert, - ), - "fundz_client": ApiClient( - config["default"]["FUNDZ_BASE_URL"], - validate_cert=validate_cert, - ), - "requests_client": ApiClient( - config["default"]["REQUESTS_QUEUE_BASE_URL"], - api_version="v1", - validate_cert=validate_cert, - ), - "sessions": RedisSessions( - redis_client, config["default"]["SESSION_TTL_SECONDS"] - ), + **config["default"], + "ENV": config["default"]["ENVIRONMENT"], + "DEBUG": config["default"]["DEBUG"], + "PORT": int(config["default"]["PORT"]), + "SQLALCHEMY_DATABASE_URI": config["default"]["DATABASE_URI"], + "SQLALCHEMY_TRACK_MODIFICATIONS": False, + "WTF_CSRF_ENABLED": config.getboolean("default", "WTF_CSRF_ENABLED"), + "PERMANENT_SESSION_LIFETIME": config.getint("default", "PERMANENT_SESSION_LIFETIME"), } @@ -190,8 +99,49 @@ def make_config(): ENV_CONFIG_FILENAME = os.path.join( os.path.dirname(__file__), "../config/", "{}.ini".format(ENV.lower()) ) + OVERRIDE_CONFIG_FILENAME = os.getenv("OVERRIDE_CONFIG_FULLPATH") + config = ConfigParser() + config.optionxform = str + + config_files = [BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME] + if OVERRIDE_CONFIG_FILENAME: + config_files.append(OVERRIDE_CONFIG_FILENAME) + + config_files = [BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME] + if OVERRIDE_CONFIG_FILENAME: + config_files.append(OVERRIDE_CONFIG_FILENAME) # ENV_CONFIG will override values in BASE_CONFIG. - config.read([BASE_CONFIG_FILENAME, ENV_CONFIG_FILENAME]) - return config + config.read(config_files) + + # Assemble DATABASE_URI value + database_uri = ( + "postgres://" + + config.get("default", "PGUSER") + + ":" + + config.get("default", "PGPASSWORD") + + "@" + + config.get("default", "PGHOST") + + ":" + + config.get("default", "PGPORT") + + "/" + + config.get("default", "PGDATABASE") + ) + config.set("default", "DATABASE_URI", database_uri) + + return map_config(config) + +def make_redis(config): + return redis.Redis.from_url(config['REDIS_URI']) + +def make_crl_validator(app): + crl_locations = [] + for filename in pathlib.Path(app.config["CRL_DIRECTORY"]).glob("*"): + crl_locations.append(filename.absolute()) + app.crl_validator = Validator( + roots=[app.config["CA_CHAIN"]], crl_locations=crl_locations + ) + for e in app.crl_validator.errors: + app.logger.error(e) + diff --git a/atst/assets.py b/atst/assets.py index 7f723f75..aaf1f82e 100644 --- a/atst/assets.py +++ b/atst/assets.py @@ -1,16 +1,16 @@ -from webassets import Environment, Bundle -from atst.home import home +from flask_assets import Environment, Bundle -environment = Environment( - directory=home.child("scss"), - url="/static" -) +environment = Environment() css = Bundle( - "atat.scss", - filters="scss", - output="../static/assets/out.%(version)s.css", - depends=("**/*.scss"), + "../static/assets/index.css", + output="../static/assets/index.%(version)s.css", ) environment.register("css", css) + +js = Bundle( + '../static/assets/index.js', + output='../static/assets/index.%(version)s.js' +) +environment.register('js_all', js) diff --git a/atst/database.py b/atst/database.py new file mode 100644 index 00000000..f0b13d6f --- /dev/null +++ b/atst/database.py @@ -0,0 +1,3 @@ +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() diff --git a/atst/handlers/__init__.py b/atst/domain/__init__.py similarity index 100% rename from atst/handlers/__init__.py rename to atst/domain/__init__.py diff --git a/atst/domain/auth.py b/atst/domain/auth.py new file mode 100644 index 00000000..c1a25c95 --- /dev/null +++ b/atst/domain/auth.py @@ -0,0 +1,32 @@ +from flask import g, redirect, url_for, session, request + +from atst.domain.users import Users + + +UNPROTECTED_ROUTES = ["atst.root", "dev.login_dev", "atst.login_redirect", "atst.unauthorized", "static"] + +def apply_authentication(app): + @app.before_request + # pylint: disable=unused-variable + def enforce_login(): + + if not _unprotected_route(request): + user = get_current_user() + if user: + g.current_user = user + + else: + return redirect(url_for("atst.root")) + + +def get_current_user(): + user_id = session.get("user_id") + if user_id: + return Users.get(user_id) + else: + return False + +def _unprotected_route(request): + if request.endpoint in UNPROTECTED_ROUTES: + return True + diff --git a/atst/domain/authnid/__init__.py b/atst/domain/authnid/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/atst/domain/authnid/crl/util.py b/atst/domain/authnid/crl/util.py new file mode 100644 index 00000000..13e8106d --- /dev/null +++ b/atst/domain/authnid/crl/util.py @@ -0,0 +1,72 @@ +import requests +import re +import os +from html.parser import HTMLParser + +_DISA_CRLS = "https://iasecontent.disa.mil/pki-pke/data/crls/dod_crldps.htm" + + +def fetch_disa(): + response = requests.get(_DISA_CRLS) + return response.text + + +class DISAParser(HTMLParser): + crl_list = [] + _CRL_MATCH = re.compile("DOD(ROOT|EMAIL|ID)?CA") + + def handle_starttag(self, tag, attrs): + if tag == "a": + href = [pair[1] for pair in attrs if pair[0] == "href"].pop() + if re.search(self._CRL_MATCH, href): + self.crl_list.append(href) + + +def crl_list_from_disa_html(html): + parser = DISAParser() + parser.reset() + parser.feed(html) + return parser.crl_list + + +def write_crl(out_dir, crl_location): + name = re.split("/", crl_location)[-1] + crl = os.path.join(out_dir, name) + with requests.get(crl_location, stream=True) as r: + with open(crl, "wb") as crl_file: + for chunk in r.iter_content(chunk_size=1024): + if chunk: + crl_file.write(chunk) + + +def refresh_crls(out_dir, logger=None): + disa_html = fetch_disa() + crl_list = crl_list_from_disa_html(disa_html) + for crl_location in crl_list: + if logger: + logger.info("updating CRL from {}".format(crl_location)) + try: + write_crl(out_dir, crl_location) + except requests.exceptions.ChunkedEncodingError: + if logger: + logger.error( + "Error downloading {}, continuing anyway".format(crl_location) + ) + + +if __name__ == "__main__": + import sys + import datetime + import logging + + logging.basicConfig( + level=logging.INFO, format="[%(asctime)s]:%(levelname)s: %(message)s" + ) + logger = logging.getLogger() + logger.info("Updating CRLs") + try: + refresh_crls(sys.argv[1], logger=logger) + except Exception as err: + logger.exception("Fatal error encountered, stopping") + sys.exit(1) + logger.info("Finished updating CRLs") diff --git a/atst/domain/authnid/crl/validator.py b/atst/domain/authnid/crl/validator.py new file mode 100644 index 00000000..409a8bf7 --- /dev/null +++ b/atst/domain/authnid/crl/validator.py @@ -0,0 +1,124 @@ +import sys +import os +import re +import hashlib +from OpenSSL import crypto, SSL + + +def sha256_checksum(filename, block_size=65536): + sha256 = hashlib.sha256() + with open(filename, "rb") as f: + for block in iter(lambda: f.read(block_size), b""): + sha256.update(block) + return sha256.hexdigest() + + +class Validator: + + _PEM_RE = re.compile( + b"-----BEGIN CERTIFICATE-----\r?.+?\r?-----END CERTIFICATE-----\r?\n?", + re.DOTALL, + ) + + def __init__(self, crl_locations=[], roots=[], base_store=crypto.X509Store): + self.errors = [] + self.crl_locations = crl_locations + self.roots = roots + self.base_store = base_store + self._reset() + + def _reset(self): + self.cache = {} + self.store = self.base_store() + self._add_crls(self.crl_locations) + self._add_roots(self.roots) + self.store.set_flags(crypto.X509StoreFlags.CRL_CHECK) + + def _add_crls(self, locations): + for filename in locations: + try: + self._add_crl(filename) + except crypto.Error as err: + self.errors.append( + "CRL could not be parsed. Filename: {}, Error: {}, args: {}".format( + filename, type(err), err.args + ) + ) + + # This caches the CRL issuer with the CRL filepath and a checksum, in addition to adding the CRL to the store. + + def _add_crl(self, filename): + with open(filename, "rb") as crl_file: + crl = crypto.load_crl(crypto.FILETYPE_ASN1, crl_file.read()) + self.cache[crl.get_issuer().der()] = (filename, sha256_checksum(filename)) + self._add_carefully("add_crl", crl) + + def _parse_roots(self, root_str): + return [match.group(0) for match in self._PEM_RE.finditer(root_str)] + + def _add_roots(self, roots): + for filename in roots: + with open(filename, "rb") as f: + for raw_ca in self._parse_roots(f.read()): + ca = crypto.load_certificate(crypto.FILETYPE_PEM, raw_ca) + self._add_carefully("add_cert", ca) + + # in testing, it seems that openssl is maintaining a local cache of certs + # in a hash table and throws errors if you try to add redundant certs or + # CRLs. For now, we catch and ignore that error with great specificity. + + def _add_carefully(self, method_name, obj): + try: + getattr(self.store, method_name)(obj) + except crypto.Error as error: + if self._is_preloaded_error(error): + pass + else: + raise error + + PRELOADED_CRL = ( + [ + ( + "x509 certificate routines", + "X509_STORE_add_crl", + "cert already in hash table", + ) + ], + ) + PRELOADED_CERT = ( + [ + ( + "x509 certificate routines", + "X509_STORE_add_cert", + "cert already in hash table", + ) + ], + ) + + def _is_preloaded_error(self, error): + return error.args == self.PRELOADED_CRL or error.args == self.PRELOADED_CERT + + # Checks that the CRL currently in-memory is up-to-date via the checksum. + + def refresh_cache(self, cert): + der = cert.get_issuer().der() + if der in self.cache: + filename, checksum = self.cache[der] + if sha256_checksum(filename) != checksum: + self._reset() + + def validate(self, cert): + parsed = crypto.load_certificate(crypto.FILETYPE_PEM, cert) + self.refresh_cache(parsed) + context = crypto.X509StoreContext(self.store, parsed) + try: + context.verify_certificate() + return True + + except crypto.X509StoreContextError as err: + self.errors.append( + "Certificate revoked or errored. Error: {}. Args: {}".format( + type(err), err.args + ) + ) + return False diff --git a/atst/domain/authnid/utils.py b/atst/domain/authnid/utils.py new file mode 100644 index 00000000..763820ce --- /dev/null +++ b/atst/domain/authnid/utils.py @@ -0,0 +1,13 @@ +import re + + +# TODO: our sample SDN does not have an email address +def parse_sdn(sdn): + try: + parts = sdn.split(",") + cn_string = [piece for piece in parts if re.match("^CN=", piece)][0] + cn = cn_string.split("=")[-1] + info = cn.split(".") + return {"last_name": info[0], "first_name": info[1], "dod_id": info[-1]} + except (IndexError, AttributeError): + raise ValueError("'{}' is not a valid SDN".format(sdn)) diff --git a/atst/domain/exceptions.py b/atst/domain/exceptions.py new file mode 100644 index 00000000..802997d4 --- /dev/null +++ b/atst/domain/exceptions.py @@ -0,0 +1,16 @@ +class NotFoundError(Exception): + def __init__(self, resource_name): + self.resource_name = resource_name + + @property + def message(self): + return "No {} could be found.".format(self.resource_name) + + +class AlreadyExistsError(Exception): + def __init__(self, resource_name): + self.resource_name = resource_name + + @property + def message(self): + return "{} already exists".format(self.resource_name) diff --git a/atst/domain/pe_numbers.py b/atst/domain/pe_numbers.py new file mode 100644 index 00000000..62f8326a --- /dev/null +++ b/atst/domain/pe_numbers.py @@ -0,0 +1,25 @@ +from sqlalchemy.dialects.postgresql import insert + +from atst.database import db +from atst.models.pe_number import PENumber +from .exceptions import NotFoundError + + +class PENumbers(object): + + @classmethod + def get(cls, number): + pe_number = db.session.query(PENumber).get(number) + if not pe_number: + raise NotFoundError("pe_number") + + return pe_number + + @classmethod + def create_many(cls, list_of_pe_numbers): + stmt = insert(PENumber).values(list_of_pe_numbers) + do_update = stmt.on_conflict_do_update( + index_elements=["number"], set_=dict(description=stmt.excluded.description) + ) + db.session.execute(do_update) + db.session.commit() diff --git a/atst/domain/requests.py b/atst/domain/requests.py new file mode 100644 index 00000000..5c04d3c7 --- /dev/null +++ b/atst/domain/requests.py @@ -0,0 +1,134 @@ +from sqlalchemy import exists, and_ +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.orm.attributes import flag_modified + +from atst.models import Request, RequestStatusEvent +from atst.database import db + +from .exceptions import NotFoundError + + +def deep_merge(source, destination: dict): + """ + Merge source dict into destination dict recursively. + """ + + def _deep_merge(a, b): + for key, value in a.items(): + if isinstance(value, dict): + node = b.setdefault(key, {}) + _deep_merge(value, node) + else: + b[key] = value + + return b + + return _deep_merge(source, dict(destination)) + + +class Requests(object): + AUTO_APPROVE_THRESHOLD = 1000000 + + @classmethod + def create(cls, creator_id, body): + request = Request(creator=creator_id, body=body) + + status_event = RequestStatusEvent(new_status="incomplete") + request.status_events.append(status_event) + + db.session.add(request) + db.session.commit() + + return request + + @classmethod + def exists(cls, request_id, creator_id): + return db.session.query( + exists().where( + and_(Request.id == request_id, Request.creator == creator_id) + ) + ).scalar() + + @classmethod + def get(cls, request_id): + try: + request = db.session.query(Request).filter_by(id=request_id).one() + except NoResultFound: + raise NotFoundError("request") + + return request + + @classmethod + def get_many(cls, creator_id=None): + filters = [] + if creator_id: + filters.append(Request.creator == creator_id) + + requests = ( + db.session.query(Request) + .filter(*filters) + .order_by(Request.time_created.desc()) + .all() + ) + return requests + + @classmethod + def submit(cls, request): + request.status_events.append(RequestStatusEvent(new_status="submitted")) + + if Requests.should_auto_approve(request): + request.status_events.append(RequestStatusEvent(new_status="approved")) + + db.session.add(request) + db.session.commit() + + return request + + @classmethod + def update(cls, request_id, request_delta): + try: + # Query for request matching id, acquiring a row-level write lock. + # https://www.postgresql.org/docs/10/static/sql-select.html#SQL-FOR-UPDATE-SHARE + request = ( + db.session.query(Request) + .filter_by(id=request_id) + .with_for_update(of=Request) + .one() + ) + except NoResultFound: + return + + request.body = deep_merge(request_delta, request.body) + + if Requests.should_allow_submission(request): + request.status_events.append( + RequestStatusEvent(new_status="pending_submission") + ) + + # Without this, sqlalchemy won't notice the change to request.body, + # since it doesn't track dictionary mutations by default. + flag_modified(request, "body") + + db.session.add(request) + db.session.commit() + + @classmethod + def should_auto_approve(cls, request): + try: + dollar_value = request.body["details_of_use"]["dollar_value"] + except KeyError: + return False + + return dollar_value < cls.AUTO_APPROVE_THRESHOLD + + @classmethod + def should_allow_submission(cls, request): + all_request_sections = [ + "details_of_use", + "information_about_you", + "primary_poc", + ] + existing_request_sections = request.body.keys() + return request.status == "incomplete" and all( + section in existing_request_sections for section in all_request_sections + ) diff --git a/atst/domain/roles.py b/atst/domain/roles.py new file mode 100644 index 00000000..1808504e --- /dev/null +++ b/atst/domain/roles.py @@ -0,0 +1,21 @@ +from sqlalchemy.orm.exc import NoResultFound + +from atst.database import db +from atst.models import Role +from .exceptions import NotFoundError + + +class Roles(object): + + @classmethod + def get(cls, role_name): + try: + role = db.session.query(Role).filter_by(name=role_name).one() + except NoResultFound: + raise NotFoundError("role") + + return role + + @classmethod + def get_all(cls): + return db.session.query(Role).all() diff --git a/atst/domain/task_orders.py b/atst/domain/task_orders.py new file mode 100644 index 00000000..5b507f53 --- /dev/null +++ b/atst/domain/task_orders.py @@ -0,0 +1,19 @@ +from sqlalchemy.orm.exc import NoResultFound + +from atst.database import db +from atst.models.task_order import TaskOrder +from .exceptions import NotFoundError + + +class TaskOrders(object): + + @classmethod + def get(self, order_number): + try: + task_order = ( + db.session.query(TaskOrder).filter_by(number=order_number).one() + ) + except NoResultFound: + raise NotFoundError("task_order") + + return task_order diff --git a/atst/domain/users.py b/atst/domain/users.py new file mode 100644 index 00000000..54cf4ae0 --- /dev/null +++ b/atst/domain/users.py @@ -0,0 +1,65 @@ +from sqlalchemy.orm.exc import NoResultFound +from sqlalchemy.exc import IntegrityError + +from atst.database import db +from atst.models import User + +from .roles import Roles +from .exceptions import NotFoundError, AlreadyExistsError + + +class Users(object): + + @classmethod + def get(cls, user_id): + try: + user = db.session.query(User).filter_by(id=user_id).one() + except NoResultFound: + raise NotFoundError("user") + + return user + + @classmethod + def get_by_dod_id(cls, dod_id): + try: + user = db.session.query(User).filter_by(dod_id=dod_id).one() + except NoResultFound: + raise NotFoundError("user") + + return user + + @classmethod + def create(cls, atat_role_name="developer", **kwargs): + atat_role = Roles.get(atat_role_name) + + try: + user = User(atat_role=atat_role, **kwargs) + db.session.add(user) + db.session.commit() + except IntegrityError: + raise AlreadyExistsError("user") + + return user + + @classmethod + def get_or_create_by_dod_id(cls, dod_id, **kwargs): + try: + user = Users.get_by_dod_id(dod_id) + except NotFoundError: + user = Users.create(dod_id=dod_id, **kwargs) + db.session.add(user) + db.session.commit() + + return user + + @classmethod + def update(cls, user_id, atat_role_name): + + user = Users.get(user_id) + atat_role = Roles.get(atat_role_name) + user.atat_role = atat_role + + db.session.add(user) + db.session.commit() + + return user diff --git a/atst/domain/workspace_users.py b/atst/domain/workspace_users.py new file mode 100644 index 00000000..7e217c38 --- /dev/null +++ b/atst/domain/workspace_users.py @@ -0,0 +1,73 @@ +from sqlalchemy.orm.exc import NoResultFound + +from atst.database import db +from atst.models.workspace_role import WorkspaceRole +from atst.models.workspace_user import WorkspaceUser +from atst.models.user import User + +from .roles import Roles +from .users import Users +from .exceptions import NotFoundError + + +class WorkspaceUsers(object): + + @classmethod + def get(cls, workspace_id, user_id): + try: + user = Users.get(user_id) + except NoResultFound: + raise NotFoundError("user") + + try: + workspace_role = ( + WorkspaceRole.query.join(User) + .filter(User.id == user_id, WorkspaceRole.workspace_id == workspace_id) + .one() + ) + except NoResultFound: + workspace_role = None + + return WorkspaceUser(user, workspace_role) + + @classmethod + def add_many(cls, workspace_id, workspace_user_dicts): + workspace_users = [] + + for user_dict in workspace_user_dicts: + try: + user = Users.get(user_dict["id"]) + except NoResultFound: + default_role = Roles.get("developer") + user = User(id=user_dict["id"], atat_role=default_role) + + try: + role = Roles.get(user_dict["workspace_role"]) + except NoResultFound: + raise NotFoundError("role") + + try: + existing_workspace_role = ( + db.session.query(WorkspaceRole) + .filter( + WorkspaceRole.user == user, + WorkspaceRole.workspace_id == workspace_id, + ) + .one() + ) + new_workspace_role = existing_workspace_role + new_workspace_role.role = role + except NoResultFound: + new_workspace_role = WorkspaceRole( + user=user, role_id=role.id, workspace_id=workspace_id + ) + + user.workspace_roles.append(new_workspace_role) + workspace_user = WorkspaceUser(user, new_workspace_role) + workspace_users.append(workspace_user) + + db.session.add(user) + + db.session.commit() + + return workspace_users diff --git a/atst/domain/workspaces.py b/atst/domain/workspaces.py index ca848425..6ec0b856 100644 --- a/atst/domain/workspaces.py +++ b/atst/domain/workspaces.py @@ -1,8 +1,4 @@ -import tornado.gen - - class Projects(object): - def __init__(self): pass @@ -50,7 +46,6 @@ class Projects(object): class Members(object): - def __init__(self): pass diff --git a/atst/eda_client.py b/atst/eda_client.py index cebaad27..e181f245 100644 --- a/atst/eda_client.py +++ b/atst/eda_client.py @@ -85,7 +85,7 @@ class MockEDAClient(EDAClientBase): "location": "https://docsrv1.nit.disa.mil:443/eda/enforcer/C0414345.PDF?ver=1.4&loc=Y29udHJhY3RzL29nZGVuL3ZlbmRvci8xOTk4LzA5LzE0L0MwNDE0MzQ1LlBERg==&sourceurl=aHR0cHM6Ly9lZGE0Lm5pdC5kaXNhLm1pbC9wbHMvdXNlci9uZXdfYXBwLkdldF9Eb2M_cFRhYmxlX0lEPTImcFJlY29yZF9LZXk9OEE2ODExNjM2RUY5NkU2M0UwMzQwMDYwQjBCMjgyNkM=&uid=6CFC2B2322E86FD5E054002264936E3C&qid=19344159&signed=G&qdate=20180529194407GMT&token=6xQICrrrfIMciEJSpXmfsAYrToM=", "pay_dodaac": None, "pco_mod": "02", - "amount": 2000000 + "amount": 2000000, } else: return None diff --git a/atst/forms/fields.py b/atst/forms/fields.py index 6f733bd1..bc542bf5 100644 --- a/atst/forms/fields.py +++ b/atst/forms/fields.py @@ -7,10 +7,7 @@ import pendulum class DateField(DateField): def _value(self): if self.data: - date_formats = [ - "YYYY-MM-DD", - "MM/DD/YYYY" - ] + date_formats = ["YYYY-MM-DD", "MM/DD/YYYY"] for _format in date_formats: try: return pendulum.from_format(self.data, _format).date() diff --git a/atst/forms/financial.py b/atst/forms/financial.py index 9c2a669c..68196837 100644 --- a/atst/forms/financial.py +++ b/atst/forms/financial.py @@ -1,22 +1,27 @@ import re -import tornado -from tornado.gen import Return from wtforms.fields.html5 import EmailField from wtforms.fields import StringField, SelectField from wtforms.form import Form from wtforms.validators import Required, Email +from atst.domain.exceptions import NotFoundError +from atst.domain.pe_numbers import PENumbers + from .fields import NewlineListField from .forms import ValidatedForm -PE_REGEX = re.compile(r""" +PE_REGEX = re.compile( + r""" (0?\d) # program identifier (0?\d) # category (\d) # activity (\d+) # sponsor element (.+) # service -""", re.X) +""", + re.X, +) + def suggest_pe_id(pe_id): suggestion = pe_id @@ -34,33 +39,28 @@ def suggest_pe_id(pe_id): return None -@tornado.gen.coroutine -def validate_pe_id(field, existing_request, fundz_client): - response = yield fundz_client.get( - "/pe-number/{}".format(field.data), - raise_error=False, - ) - if not response.ok: +def validate_pe_id(field, existing_request): + try: + pe_number = PENumbers.get(field.data) + except NotFoundError: suggestion = suggest_pe_id(field.data) error_str = ( "We couldn't find that PE number. {}" "If you have double checked it you can submit anyway. " "Your request will need to go through a manual review." - ).format("Did you mean \"{}\"? ".format(suggestion) if suggestion else "") - field.errors.append(error_str) + ).format('Did you mean "{}"? '.format(suggestion) if suggestion else "") + field.errors += (error_str,) return False return True class FinancialForm(ValidatedForm): - - @tornado.gen.coroutine - def perform_extra_validation(self, existing_request, fundz_client): + def perform_extra_validation(self, existing_request): valid = True - if not existing_request or existing_request.get('pe_id') != self.pe_id.data: - valid = yield validate_pe_id(self.pe_id, existing_request, fundz_client) - raise Return(valid) + if not existing_request or existing_request.get("pe_id") != self.pe_id.data: + valid = validate_pe_id(self.pe_id, existing_request) + return valid task_order_id = StringField( "Task Order Number associated with this request.", validators=[Required()] @@ -70,9 +70,7 @@ class FinancialForm(ValidatedForm): "Unique Item Identifier (UII)s related to your application(s) if you already have them." ) - pe_id = StringField( - "Program Element (PE) Number related to your request" - ) + pe_id = StringField("Program Element (PE) Number related to your request") treasury_code = StringField("Program Treasury Code") @@ -118,11 +116,13 @@ class FinancialForm(ValidatedForm): ) clin_0001 = StringField( - "
CLIN 0001
-
Unclassified IaaS and PaaS Amount
", validators=[Required()] + "
CLIN 0001
-
Unclassified IaaS and PaaS Amount
", + validators=[Required()], ) clin_0003 = StringField( - "
CLIN 0003
-
Unclassified Cloud Support Package
", validators=[Required()] + "
CLIN 0003
-
Unclassified Cloud Support Package
", + validators=[Required()], ) clin_1001 = StringField( diff --git a/atst/forms/forms.py b/atst/forms/forms.py index c3ea02c4..2aaa4973 100644 --- a/atst/forms/forms.py +++ b/atst/forms/forms.py @@ -1,12 +1,8 @@ -import tornado -from tornado.gen import Return -from wtforms_tornado import Form +from flask_wtf import FlaskForm -class ValidatedForm(Form): - - @tornado.gen.coroutine +class ValidatedForm(FlaskForm): def perform_extra_validation(self, *args, **kwargs): - """A coroutine that performs any applicable extra validation. Must + """Performs any applicable extra validation. Must return True if the form is valid or False otherwise.""" - raise Return(True) + return True diff --git a/atst/forms/org.py b/atst/forms/org.py index b2bad0ee..7fc21986 100644 --- a/atst/forms/org.py +++ b/atst/forms/org.py @@ -8,30 +8,15 @@ from .validators import DateRange, PhoneNumber, Alphabet class OrgForm(ValidatedForm): - fname_request = StringField( - "First Name", - validators=[Required(), Alphabet()] - ) + fname_request = StringField("First Name", validators=[Required(), Alphabet()]) - lname_request = StringField( - "Last Name", - validators=[Required(), Alphabet()] - ) + lname_request = StringField("Last Name", validators=[Required(), Alphabet()]) - email_request = EmailField( - "Email Address", - validators=[Required(), Email()] - ) + email_request = EmailField("Email Address", validators=[Required(), Email()]) - phone_number = TelField( - "Phone Number", - validators=[Required(), PhoneNumber()] - ) + phone_number = TelField("Phone Number", validators=[Required(), PhoneNumber()]) - service_branch = StringField( - "Service Branch or Agency", - validators=[Required()] - ) + service_branch = StringField("Service Branch or Agency", validators=[Required()]) citizenship = RadioField( choices=[ diff --git a/atst/forms/poc.py b/atst/forms/poc.py index 24ce108b..66b77064 100644 --- a/atst/forms/poc.py +++ b/atst/forms/poc.py @@ -6,22 +6,12 @@ from .validators import IsNumber, Alphabet class POCForm(ValidatedForm): - fname_poc = StringField( - "POC First Name", - validators=[Required()] - ) + fname_poc = StringField("POC First Name", validators=[Required()]) - lname_poc = StringField( - "POC Last Name", - validators=[Required()] - ) + lname_poc = StringField("POC Last Name", validators=[Required()]) - email_poc = EmailField( - "POC Email Address", - validators=[Required(), Email()] - ) + email_poc = EmailField("POC Email Address", validators=[Required(), Email()]) dodid_poc = StringField( - "DOD ID", - validators=[Required(), Length(min=10), IsNumber()] + "DOD ID", validators=[Required(), Length(min=10), IsNumber()] ) diff --git a/atst/forms/request.py b/atst/forms/request.py index 48f128d1..f15e9140 100644 --- a/atst/forms/request.py +++ b/atst/forms/request.py @@ -14,18 +14,21 @@ class RequestForm(ValidatedForm): "DoD Component", description="Identify the DoD component that is requesting access to the JEDI Cloud", choices=[ - ("null","Select an option"), - ("us_air_force","US Air Force"), - ("us_army","US Army"), - ("us_navy","US Navy"), - ("us_marine_corps","US Marine Corps"), - ("joint_chiefs_of_staff","Joint Chiefs of Staff")], + ("null", "Select an option"), + ("us_air_force", "US Air Force"), + ("us_army", "US Army"), + ("us_navy", "US Navy"), + ("us_marine_corps", "US Marine Corps"), + ("joint_chiefs_of_staff", "Joint Chiefs of Staff"), + ], ) jedi_usage = TextAreaField( "JEDI Usage", description="Briefly describe how you are expecting to use the JEDI Cloud", - render_kw={"placeholder": "e.g. We are migrating XYZ application to the cloud so that..."}, + render_kw={ + "placeholder": "e.g. We are migrating XYZ application to the cloud so that..." + }, ) # Details of Use: Cloud Readiness @@ -41,7 +44,7 @@ class RequestForm(ValidatedForm): rationalization_software_systems = RadioField( "Have you completed a “rationalization” of your software systems to move to the cloud?", - choices=[("yes", "Yes"), ("no", "No"), ("in_progress","In Progress")], + choices=[("yes", "Yes"), ("no", "No"), ("in_progress", "In Progress")], ) technical_support_team = RadioField( @@ -52,40 +55,43 @@ class RequestForm(ValidatedForm): organization_providing_assistance = RadioField( # this needs to be updated to use checkboxes instead of radio "If you are receiving migration assistance, indicate the type of organization providing assistance below:", choices=[ - ("in_house_staff","In-house staff"), - ("contractor","Contractor"), - ("other_dod_organization","Other DoD organization")], + ("in_house_staff", "In-house staff"), + ("contractor", "Contractor"), + ("other_dod_organization", "Other DoD organization"), + ], ) engineering_assessment = RadioField( description="Have you completed an engineering assessment of your software systems for cloud readiness?", - choices=[("yes", "Yes"), ("no", "No"), ("in_progress","In Progress")], + choices=[("yes", "Yes"), ("no", "No"), ("in_progress", "In Progress")], ) data_transfers = SelectField( description="How much data is being transferred to the cloud?", choices=[ - ("null","Select an option"), - ("less_than_100gb","Less than 100GB"), - ("100gb-500gb","100GB-500GB"), - ("500gb-1tb","500GB-1TB"), - ("1tb-50tb","1TB-50TB"), - ("50tb-100tb","50TB-100TB"), - ("100tb-500tb","100TB-500TB"), - ("500tb-1pb","500TB-1PB"), - ("1pb-5pb","1PB-5PB"), - ("5pb-10pb","5PB-10PB"), - ("above_10pb","Above 10PB")], + ("null", "Select an option"), + ("less_than_100gb", "Less than 100GB"), + ("100gb-500gb", "100GB-500GB"), + ("500gb-1tb", "500GB-1TB"), + ("1tb-50tb", "1TB-50TB"), + ("50tb-100tb", "50TB-100TB"), + ("100tb-500tb", "100TB-500TB"), + ("500tb-1pb", "500TB-1PB"), + ("1pb-5pb", "1PB-5PB"), + ("5pb-10pb", "5PB-10PB"), + ("above_10pb", "Above 10PB"), + ], ) expected_completion_date = SelectField( description="When do you expect to complete your migration to the JEDI Cloud?", choices=[ - ("null","Select an option"), - ("less_than_1_month","Less than 1 month"), - ("1_to_3_months","1-3 months"), - ("3_to_6_months","3-6 months"), - ("above_12_months","Above 12 months")], + ("null", "Select an option"), + ("less_than_1_month", "Less than 1 month"), + ("1_to_3_months", "1-3 months"), + ("3_to_6_months", "3-6 months"), + ("above_12_months", "Above 12 months"), + ], ) cloud_native = RadioField( @@ -96,7 +102,7 @@ class RequestForm(ValidatedForm): # Details of Use: Financial Usage estimated_monthly_spend = IntegerField( "Estimated monthly spend", - description="Use the JEDI CSP Calculator to estimate your monthly cloud resource usage and enter the dollar amount below. Note these estimates are for initial approval only. After the request is approved, you will be asked to provide a valid Task Order number with specific CLIN amounts for cloud services." + description='Use the JEDI CSP Calculator to estimate your monthly cloud resource usage and enter the dollar amount below. Note these estimates are for initial approval only. After the request is approved, you will be asked to provide a valid Task Order number with specific CLIN amounts for cloud services.', ) dollar_value = IntegerField( @@ -105,17 +111,13 @@ class RequestForm(ValidatedForm): ) number_user_sessions = IntegerField( - description="How many user sessions do you expect on these systems each day?", + description="How many user sessions do you expect on these systems each day?" ) average_daily_traffic = IntegerField( - description="What is the average daily traffic you expect the systems under this cloud contract to use?", + description="What is the average daily traffic you expect the systems under this cloud contract to use?" ) start_date = DateField( - description="When do you expect to start using the JEDI Cloud (not for billing purposes)?", + description="When do you expect to start using the JEDI Cloud (not for billing purposes)?" ) - - - - diff --git a/atst/handler.py b/atst/handler.py deleted file mode 100644 index 3766aa95..00000000 --- a/atst/handler.py +++ /dev/null @@ -1,51 +0,0 @@ -import tornado.web -from atst.assets import environment -from atst.sessions import SessionNotFoundError - -helpers = {"assets": environment} - - -class BaseHandler(tornado.web.RequestHandler): - - def get_template_namespace(self): - ns = super(BaseHandler, self).get_template_namespace() - helpers["config"] = self.application.config - ns.update(helpers) - return ns - - @tornado.gen.coroutine - def login(self, user): - user_permissions = yield self._get_user_permissions(user["id"]) - user["atat_permissions"] = user_permissions["atat_permissions"] - user["atat_role"] = user_permissions["atat_role"] - session_id = self.sessions.start_session(user) - self.set_secure_cookie("atat", session_id) - return self.redirect("/home") - - @tornado.gen.coroutine - def _get_user_permissions(self, user_id): - response = yield self.authz_client.get( - "/users/{}".format(user_id), raise_error=False - ) - if response.code == 404: - response = yield self.authz_client.post( - "/users", json={"id": user_id, "atat_role": "developer"} - ) - return response.json - - else: - return response.json - - def get_current_user(self): - cookie = self.get_secure_cookie("atat") - if cookie: - try: - session = self.application.sessions.get_session(cookie) - except SessionNotFoundError: - self.clear_cookie("atat") - return None - - else: - return None - - return session["user"] diff --git a/atst/handlers/dev.py b/atst/handlers/dev.py deleted file mode 100644 index 878aca11..00000000 --- a/atst/handlers/dev.py +++ /dev/null @@ -1,64 +0,0 @@ -import tornado.gen - -from atst.handler import BaseHandler - -_DEV_USERS = { - "sam": { - "id": "164497f6-c1ea-4f42-a5ef-101da278c012", - "first_name": "Sam", - "last_name": "Seeceepio", - "atat_role": "ccpo" - }, - - "amanda": { - "id": "cce17030-4109-4719-b958-ed109dbb87c8", - "first_name": "Amanda", - "last_name": "Adamson", - "atat_role": "default" - }, - "brandon": { - "id": "66ebf7b8-cbf0-4ed8-a102-5f105330df75", - "first_name": "Brandon", - "last_name": "Buchannan", - "atat_role": "default" - }, - "christina": { - "id": "7707b9f2-5945-49ae-967a-be65baa88baf", - "first_name": "Christina", - "last_name": "Collins", - "atat_role": "default" - }, - "dominick": { - "id": "6978ac0c-442a-46aa-a0c3-ff17b5ec2a8c", - "first_name": "Dominick", - "last_name": "Domingo", - "atat_role": "default" - }, - "erica": { - "id": "596fd001-bb1d-4adf-87d8-fa2312e882de", - "first_name": "Erica", - "last_name": "Eichner", - "atat_role": "default" - }, -} - -class Dev(BaseHandler): - - def initialize(self, action, sessions, authz_client): - self.action = action - self.sessions = sessions - self.authz_client = authz_client - - @tornado.gen.coroutine - def get(self): - role = self.get_argument("username", "amanda") - user = _DEV_USERS[role] - yield self._set_user_permissions(user["id"], user["atat_role"]) - yield self.login(user) - - @tornado.gen.coroutine - def _set_user_permissions(self, user_id, role): - response = yield self.authz_client.post( - "/users", json={"id": user_id, "atat_role": role} - ) - return response.json diff --git a/atst/handlers/login_redirect.py b/atst/handlers/login_redirect.py deleted file mode 100644 index 59fb8751..00000000 --- a/atst/handlers/login_redirect.py +++ /dev/null @@ -1,38 +0,0 @@ -import tornado -from atst.handler import BaseHandler - - -class LoginRedirect(BaseHandler): - def initialize(self, authnid_client, sessions, authz_client): - self.authnid_client = authnid_client - self.sessions = sessions - self.authz_client = authz_client - - @tornado.gen.coroutine - def get(self): - token = self.get_query_argument("bearer-token") - if token: - user = yield self._fetch_user_info(token) - if user: - yield self.login(user) - else: - self.write_error(401) - - url = self.get_login_url() - self.redirect(url) - - @tornado.gen.coroutine - def _fetch_user_info(self, token): - try: - response = yield self.authnid_client.post( - "/validate", json={"token": token} - ) - if response.code == 200: - return response.json["user"] - - except tornado.httpclient.HTTPError as error: - if error.response.code == 401: - return None - - else: - raise error diff --git a/atst/handlers/main.py b/atst/handlers/main.py deleted file mode 100644 index 737d3bd7..00000000 --- a/atst/handlers/main.py +++ /dev/null @@ -1,11 +0,0 @@ -import tornado -from atst.handler import BaseHandler - - -class Main(BaseHandler): - def initialize(self, page): - self.page = page - - @tornado.web.authenticated - def get(self): - self.render("%s.html.to" % self.page, page=self.page) diff --git a/atst/handlers/request.py b/atst/handlers/request.py deleted file mode 100644 index d9bec160..00000000 --- a/atst/handlers/request.py +++ /dev/null @@ -1,43 +0,0 @@ -import tornado -import pendulum - -from atst.handler import BaseHandler - - -def map_request(user, request): - time_created = pendulum.parse(request["time_created"]) - is_new = time_created.add(days=1) > pendulum.now() - - return { - "order_id": request["id"], - "is_new": is_new, - "status": request["status"], - "app_count": 1, - "date": time_created.format("M/DD/YYYY"), - "full_name": "{} {}".format(user["first_name"], user["last_name"]), - } - - -class Request(BaseHandler): - def initialize(self, page, requests_client): - self.page = page - self.requests_client = requests_client - - @tornado.web.authenticated - @tornado.gen.coroutine - def get(self): - user = self.get_current_user() - requests = yield self.fetch_requests(user) - mapped_requests = [map_request(user, request) for request in requests] - self.render("requests.html.to", page=self.page, requests=mapped_requests) - - @tornado.gen.coroutine - def fetch_requests(self, user): - if "review_and_approve_jedi_workspace_request" in user["atat_permissions"]: - response = yield self.requests_client.get("/requests") - else: - response = yield self.requests_client.get( - "/requests?creator_id={}".format(user["id"]) - ) - - return response.json["requests"] diff --git a/atst/handlers/request_financial_verification.py b/atst/handlers/request_financial_verification.py deleted file mode 100644 index 4c81f9d7..00000000 --- a/atst/handlers/request_financial_verification.py +++ /dev/null @@ -1,75 +0,0 @@ -import tornado - -from atst.handler import BaseHandler -from atst.forms.financial import FinancialForm - - -class RequestFinancialVerification(BaseHandler): - def initialize(self, page, requests_client, fundz_client): - self.page = page - self.requests_client = requests_client - self.fundz_client = fundz_client - - @tornado.gen.coroutine - def get_existing_request(self, request_id): - if request_id is None: - return {} - request = yield self.requests_client.get("/requests/{}".format(request_id)) - return request.json - - @tornado.web.authenticated - @tornado.gen.coroutine - def get(self, request_id=None): - existing_request = yield self.get_existing_request(request_id) - form = FinancialForm(data=existing_request['body'].get('financial_verification')) - self.render( - "requests/financial_verification.html.to", - page=self.page, - f=form, - request_id=request_id, - ) - - @tornado.gen.coroutine - def update_request(self, request_id, form_data): - request_data = { - "creator_id": self.current_user["id"], - "request": {"financial_verification": form_data}, - } - response = yield self.requests_client.patch( - "/requests/{}".format(request_id), json=request_data - ) - return response - - @tornado.web.authenticated - @tornado.gen.coroutine - def post(self, request_id=None): - self.check_xsrf_cookie() - post_data = self.request.arguments - existing_request = yield self.get_existing_request(request_id) - form = FinancialForm(post_data) - - rerender_args = dict(request_id=request_id, f=form) - - if form.validate(): - response = yield self.update_request(request_id, form.data) - if response.ok: - valid = yield form.perform_extra_validation( - existing_request.get('body', {}).get('financial_verification'), - self.fundz_client - ) - if valid: - self.redirect( - self.application.default_router.reverse_url("financial_verification_submitted") - ) - else: - self.render( - "requests/financial_verification.html.to", - **rerender_args - ) - else: - self.set_status(response.code) - else: - self.render( - "requests/financial_verification.html.to", - **rerender_args - ) diff --git a/atst/handlers/request_new.py b/atst/handlers/request_new.py deleted file mode 100644 index d71c307e..00000000 --- a/atst/handlers/request_new.py +++ /dev/null @@ -1,240 +0,0 @@ -import tornado -from collections import defaultdict - -from atst.handler import BaseHandler -from atst.forms.request import RequestForm -from atst.forms.org import OrgForm -from atst.forms.poc import POCForm -from atst.forms.review import ReviewForm - - -class RequestNew(BaseHandler): - def initialize(self, page, requests_client, fundz_client): - self.page = page - self.requests_client = requests_client - self.fundz_client = fundz_client - - @tornado.gen.coroutine - def get_existing_request(self, request_id): - if request_id is None: - return {} - request = yield self.requests_client.get("/requests/{}".format(request_id)) - return request.json - - @tornado.web.authenticated - @tornado.gen.coroutine - def post(self, screen=1, request_id=None): - self.check_xsrf_cookie() - screen = int(screen) - post_data = self.request.arguments - current_user = self.get_current_user() - existing_request = yield self.get_existing_request(request_id) - jedi_flow = JEDIRequestFlow( - self.requests_client, - self.fundz_client, - screen, - post_data=post_data, - request_id=request_id, - current_user=current_user, - existing_request=existing_request, - ) - - rerender_args = dict( - f=jedi_flow.form, - data=post_data, - page=self.page, - screens=jedi_flow.screens, - current=screen, - next_screen=jedi_flow.next_screen, - request_id=jedi_flow.request_id, - ) - - if jedi_flow.validate(): - response = yield jedi_flow.create_or_update_request() - if response.ok: - valid = yield jedi_flow.validate_warnings() - if valid: - if jedi_flow.next_screen > len(jedi_flow.screens): - where = "/requests" - else: - where = self.application.default_router.reverse_url( - "request_form_update", jedi_flow.next_screen, jedi_flow.request_id - ) - self.redirect(where) - else: - self.render( - "requests/screen-%d.html.to" % int(screen), - **rerender_args - ) - else: - self.set_status(response.code) - else: - self.render( - "requests/screen-%d.html.to" % int(screen), - **rerender_args - ) - - @tornado.web.authenticated - @tornado.gen.coroutine - def get(self, screen=1, request_id=None): - screen = int(screen) - request = None - - if request_id: - response = yield self.requests_client.get( - "/requests/{}".format(request_id), - raise_error=False, - ) - if response.ok: - request = response.json - - jedi_flow = JEDIRequestFlow( - self.requests_client, self.fundz_client, screen, request, request_id=request_id - ) - - self.render( - "requests/screen-%d.html.to" % int(screen), - f=jedi_flow.form, - data=jedi_flow.current_step_data, - page=self.page, - screens=jedi_flow.screens, - current=screen, - next_screen=screen + 1, - request_id=request_id, - can_submit=jedi_flow.can_submit - ) - - -class JEDIRequestFlow(object): - def __init__( - self, - requests_client, - fundz_client, - current_step, - request=None, - post_data=None, - request_id=None, - current_user=None, - existing_request=None, - ): - self.requests_client = requests_client - self.fundz_client = fundz_client - - self.current_step = current_step - self.request = request - - self.post_data = post_data - self.is_post = self.post_data is not None - - self.request_id = request_id - self.form = self._form() - - self.current_user = current_user - self.existing_request = existing_request - - def _form(self): - if self.is_post: - return self.form_class()(self.post_data) - elif self.request: - return self.form_class()(data=self.current_step_data) - else: - return self.form_class()() - - def validate(self): - return self.form.validate() - - @tornado.gen.coroutine - def validate_warnings(self): - valid = yield self.form.perform_extra_validation( - self.existing_request.get('body', {}).get(self.form_section), - self.fundz_client, - ) - return valid - - @property - def current_screen(self): - return self.screens[self.current_step - 1] - - @property - def form_section(self): - return self.current_screen["section"] - - def form_class(self): - return self.current_screen["form"] - - @property - def current_step_data(self): - data = {} - - if self.is_post: - data = self.post_data - - if self.request: - if self.form_section == "review_submit": - data = self.request["body"] - else: - data = self.request["body"].get(self.form_section, {}) - - return defaultdict(lambda: defaultdict(lambda: 'Input required'), data) - - @property - def can_submit(self): - return self.request and self.request["status"] != "incomplete" - - @property - def next_screen(self): - return self.current_step + 1 - - @property - def screens(self): - return [ - { - "title": "Details of Use", - "section": "details_of_use", - "form": RequestForm, - "subitems": [ - { - "title": "Overall request details", - "id": "overall-request-details", - }, - {"title": "Cloud Resources", "id": "cloud-resources"}, - {"title": "Support Staff", "id": "support-staff"}, - ], - "show": True, - }, - { - "title": "Information About You", - "section": "information_about_you", - "form": OrgForm, - "show": True, - }, - { - "title": "Primary Point of Contact", - "section": "primary_poc", - "form": POCForm, - "show": True, - }, - { - "title": "Review & Submit", - "section": "review_submit", - "form": ReviewForm, - "show":True, - }, - ] - - @tornado.gen.coroutine - def create_or_update_request(self): - request_data = { - "creator_id": self.current_user["id"], - "request": {self.form_section: self.form.data}, - } - if self.request_id: - response = yield self.requests_client.patch( - "/requests/{}".format(self.request_id), json=request_data - ) - else: - response = yield self.requests_client.post("/requests", json=request_data) - self.request = response.json - self.request_id = self.request["id"] - - return response diff --git a/atst/handlers/request_submit.py b/atst/handlers/request_submit.py deleted file mode 100644 index f4d19b3d..00000000 --- a/atst/handlers/request_submit.py +++ /dev/null @@ -1,29 +0,0 @@ -import tornado - -from atst.handler import BaseHandler - - -class RequestsSubmit(BaseHandler): - def initialize(self, requests_client): - self.requests_client = requests_client - - @tornado.web.authenticated - @tornado.gen.coroutine - def post(self, request_id): - yield self.requests_client.post( - "/requests/{}/submit".format(request_id), - allow_nonstandard_methods=True - ) - approved = yield self._check_approved(request_id) - if approved: - self.redirect("/requests?modal=True") - else: - self.redirect("/requests") - - @tornado.gen.coroutine - def _check_approved(self, request_id): - response = yield self.requests_client.get( - "/requests/{}".format(request_id) - ) - status = response.json.get("status") - return status == "approved" diff --git a/atst/handlers/root.py b/atst/handlers/root.py deleted file mode 100644 index ec68bfcc..00000000 --- a/atst/handlers/root.py +++ /dev/null @@ -1,9 +0,0 @@ -from atst.handler import BaseHandler - - -class Root(BaseHandler): - def initialize(self, page): - self.page = page - - def get(self): - self.render("%s.html.to" % self.page, page=self.page) diff --git a/atst/handlers/workspace.py b/atst/handlers/workspace.py deleted file mode 100644 index a14458a6..00000000 --- a/atst/handlers/workspace.py +++ /dev/null @@ -1,15 +0,0 @@ -import tornado - -from atst.handler import BaseHandler -from atst.domain.workspaces import Projects - - -class Workspace(BaseHandler): - def initialize(self): - self.projects_repo = Projects() - - @tornado.web.authenticated - @tornado.gen.coroutine - def get(self, workspace_id): - projects = self.projects_repo.get_many(workspace_id) - self.render("workspace_projects.html.to", workspace_id=workspace_id, projects=projects) diff --git a/atst/handlers/workspace_members.py b/atst/handlers/workspace_members.py deleted file mode 100644 index 9ffa7958..00000000 --- a/atst/handlers/workspace_members.py +++ /dev/null @@ -1,15 +0,0 @@ -import tornado - -from atst.handler import BaseHandler -from atst.domain.workspaces import Members - - -class WorkspaceMembers(BaseHandler): - def initialize(self): - self.members_repo = Members() - - @tornado.web.authenticated - @tornado.gen.coroutine - def get(self, workspace_id): - members = self.members_repo.get_many(workspace_id) - self.render("workspace_members.html.to", workspace_id=workspace_id, members=members) diff --git a/atst/handlers/workspaces.py b/atst/handlers/workspaces.py deleted file mode 100644 index c7e06451..00000000 --- a/atst/handlers/workspaces.py +++ /dev/null @@ -1,22 +0,0 @@ -from atst.handler import BaseHandler -import tornado - -mock_workspaces = [ - { - "name": "Unclassified IaaS and PaaS for Defense Digital Service (DDS)", - "id": "5966187a-eff9-44c3-aa15-4de7a65ac7ff", - "task_order": {"number": 123456}, - "user_count": 23, - } -] - - -class Workspaces(BaseHandler): - def initialize(self, page, authz_client): - self.page = page - self.authz_client = authz_client - - @tornado.gen.coroutine - @tornado.web.authenticated - def get(self): - self.render("workspaces.html.to", page=self.page, workspaces=mock_workspaces) diff --git a/atst/home.py b/atst/home.py deleted file mode 100644 index 883ec8dd..00000000 --- a/atst/home.py +++ /dev/null @@ -1,3 +0,0 @@ -from unipath import Path - -home = Path(__file__).parent.parent diff --git a/atst/models/__init__.py b/atst/models/__init__.py new file mode 100644 index 00000000..1d6daae1 --- /dev/null +++ b/atst/models/__init__.py @@ -0,0 +1,12 @@ +from sqlalchemy.ext.declarative import declarative_base + +Base = declarative_base() + +from .request import Request +from .request_status_event import RequestStatusEvent +from .permissions import Permissions +from .role import Role +from .user import User +from .workspace_role import WorkspaceRole +from .pe_number import PENumber +from .task_order import TaskOrder diff --git a/atst/models/pe_number.py b/atst/models/pe_number.py new file mode 100644 index 00000000..8cb5a52f --- /dev/null +++ b/atst/models/pe_number.py @@ -0,0 +1,15 @@ +from sqlalchemy import String, Column + +from atst.models import Base + + +class PENumber(Base): + __tablename__ = "pe_number" + + number = Column(String, primary_key=True) + description = Column(String) + + def __repr__(self): + return "".format( + self.number, self.description + ) diff --git a/atst/models/permissions.py b/atst/models/permissions.py new file mode 100644 index 00000000..9536348f --- /dev/null +++ b/atst/models/permissions.py @@ -0,0 +1,40 @@ +class Permissions(object): + REQUEST_JEDI_WORKSPACE = "request_jedi_workspace" + VIEW_ORIGINAL_JEDI_REQEUST = "view_original_jedi_request" + REVIEW_AND_APPROVE_JEDI_WORKSPACE_REQUEST = ( + "review_and_approve_jedi_workspace_request" + ) + MODIFY_ATAT_ROLE_PERMISSIONS = "modify_atat_role_permissions" + CREATE_CSP_ROLE = "create_csp_role" + DELETE_CSP_ROLE = "delete_csp_role" + DEACTIVE_CSP_ROLE = "deactivate_csp_role" + MODIFY_CSP_ROLE_PERMISSIONS = "modify_csp_role_permissions" + + VIEW_USAGE_REPORT = "view_usage_report" + VIEW_USAGE_DOLLARS = "view_usage_dollars" + ADD_AND_ASSIGN_CSP_ROLES = "add_and_assign_csp_roles" + REMOVE_CSP_ROLES = "remove_csp_roles" + REQUEST_NEW_CSP_ROLE = "request_new_csp_role" + ASSIGN_AND_UNASSIGN_ATAT_ROLE = "assign_and_unassign_atat_role" + + VIEW_ASSIGNED_ATAT_ROLE_CONFIGURATIONS = "view_assigned_atat_role_configurations" + VIEW_ASSIGNED_CSP_ROLE_CONFIGURATIONS = "view_assigned_csp_role_configurations" + + DEACTIVATE_WORKSPACE = "deactivate_workspace" + VIEW_ATAT_PERMISSIONS = "view_atat_permissions" + TRANSFER_OWNERSHIP_OF_WORKSPACE = "transfer_ownership_of_workspace" + + ADD_APPLICATION_IN_WORKSPACE = "add_application_in_workspace" + DELETE_APPLICATION_IN_WORKSPACE = "delete_application_in_workspace" + DEACTIVATE_APPLICATION_IN_WORKSPACE = "deactivate_application_in_workspace" + VIEW_APPLICATION_IN_WORKSPACE = "view_application_in_workspace" + RENAME_APPLICATION_IN_WORKSPACE = "rename_application_in_workspace" + + ADD_ENVIRONMENT_IN_APPLICATION = "add_environment_in_application" + DELETE_ENVIRONMENT_IN_APPLICATION = "delete_environment_in_application" + DEACTIVATE_ENVIRONMENT_IN_APPLICATION = "deactivate_environment_in_application" + VIEW_ENVIRONMENT_IN_APPLICATION = "view_environment_in_application" + RENAME_ENVIRONMENT_IN_APPLICATION = "rename_environment_in_application" + + ADD_TAG_TO_WORKSPACE = "add_tag_to_workspace" + REMOVE_TAG_FROM_WORKSPACE = "remove_tag_from_workspace" diff --git a/atst/models/request.py b/atst/models/request.py new file mode 100644 index 00000000..e8690332 --- /dev/null +++ b/atst/models/request.py @@ -0,0 +1,32 @@ +from sqlalchemy import Column, func +from sqlalchemy.types import DateTime +from sqlalchemy.dialects.postgresql import JSONB, UUID +from sqlalchemy.orm import relationship + +from atst.models import Base +from atst.models.types import Id + + +class Request(Base): + __tablename__ = "requests" + + id = Id() + creator = Column(UUID(as_uuid=True)) + time_created = Column(DateTime(timezone=True), server_default=func.now()) + body = Column(JSONB) + status_events = relationship( + "RequestStatusEvent", backref="request", order_by="RequestStatusEvent.sequence" + ) + + @property + def status(self): + return self.status_events[-1].new_status + + @property + def action_required_by(self): + return { + "incomplete": "mission_owner", + "pending_submission": "mission_owner", + "submitted": "ccpo", + "approved": "mission_owner", + }.get(self.status) diff --git a/atst/models/request_status_event.py b/atst/models/request_status_event.py new file mode 100644 index 00000000..4f65a2ec --- /dev/null +++ b/atst/models/request_status_event.py @@ -0,0 +1,21 @@ +from sqlalchemy import Column, func, ForeignKey +from sqlalchemy.types import DateTime, String, BigInteger +from sqlalchemy.schema import Sequence +from sqlalchemy.dialects.postgresql import UUID + +from atst.models import Base +from atst.models.types import Id + + +class RequestStatusEvent(Base): + __tablename__ = "request_status_events" + + id = Id() + new_status = Column(String()) + time_created = Column(DateTime(timezone=True), server_default=func.now()) + request_id = Column( + UUID(as_uuid=True), ForeignKey("requests.id", ondelete="CASCADE") + ) + sequence = Column( + BigInteger, Sequence("request_status_events_sequence_seq"), nullable=False + ) diff --git a/atst/models/role.py b/atst/models/role.py new file mode 100644 index 00000000..1205dedd --- /dev/null +++ b/atst/models/role.py @@ -0,0 +1,14 @@ +from sqlalchemy import String, Column +from sqlalchemy.dialects.postgresql import ARRAY + +from atst.models import Base +from .types import Id + + +class Role(Base): + __tablename__ = "roles" + + id = Id() + name = Column(String, index=True, unique=True) + description = Column(String) + permissions = Column(ARRAY(String), index=True, server_default="{}") diff --git a/atst/models/task_order.py b/atst/models/task_order.py new file mode 100644 index 00000000..6bacb913 --- /dev/null +++ b/atst/models/task_order.py @@ -0,0 +1,10 @@ +from sqlalchemy import Column, Integer, String + +from atst.models import Base + + +class TaskOrder(Base): + __tablename__ = "task_order" + + id = Column(Integer, primary_key=True) + number = Column(String) diff --git a/atst/models/types.py b/atst/models/types.py new file mode 100644 index 00000000..5a074b8c --- /dev/null +++ b/atst/models/types.py @@ -0,0 +1,11 @@ +import sqlalchemy +from sqlalchemy import Column +from sqlalchemy.dialects.postgresql import UUID + + +def Id(): + return Column( + UUID(as_uuid=True), + primary_key=True, + server_default=sqlalchemy.text("uuid_generate_v4()"), + ) diff --git a/atst/models/user.py b/atst/models/user.py new file mode 100644 index 00000000..643fd3f5 --- /dev/null +++ b/atst/models/user.py @@ -0,0 +1,30 @@ +from sqlalchemy import String, ForeignKey, Column +from sqlalchemy.orm import relationship +from sqlalchemy.dialects.postgresql import UUID + +from atst.models import Base +from .types import Id + + +class User(Base): + __tablename__ = "users" + + id = Id() + username = Column(String) + atat_role_id = Column(UUID(as_uuid=True), ForeignKey("roles.id")) + + atat_role = relationship("Role") + workspace_roles = relationship("WorkspaceRole", backref="user") + + email = Column(String, unique=True) + dod_id = Column(String, unique=True) + first_name = Column(String) + last_name = Column(String) + + @property + def atat_permissions(self): + return self.atat_role.permissions + + @property + def full_name(self): + return "{} {}".format(self.first_name, self.last_name) diff --git a/atst/models/workspace_role.py b/atst/models/workspace_role.py new file mode 100644 index 00000000..86970e0b --- /dev/null +++ b/atst/models/workspace_role.py @@ -0,0 +1,24 @@ +from sqlalchemy import Index, ForeignKey, Column +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship + +from atst.models import Base +from .types import Id + + +class WorkspaceRole(Base): + __tablename__ = "workspace_role" + + id = Id() + workspace_id = Column(UUID(as_uuid=True), index=True) + role_id = Column(UUID(as_uuid=True), ForeignKey("roles.id")) + user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"), index=True) + role = relationship("Role") + + +Index( + "workspace_role_user_workspace", + WorkspaceRole.user_id, + WorkspaceRole.workspace_id, + unique=True, +) diff --git a/atst/models/workspace_user.py b/atst/models/workspace_user.py new file mode 100644 index 00000000..6faba2d6 --- /dev/null +++ b/atst/models/workspace_user.py @@ -0,0 +1,14 @@ +class WorkspaceUser(object): + def __init__(self, user, workspace_role): + self.user = user + self.workspace_role = workspace_role + + def permissions(self): + atat_permissions = set(self.user.atat_role.permissions) + workspace_permissions = ( + [] if self.workspace_role is None else self.workspace_role.role.permissions + ) + return set(workspace_permissions).union(atat_permissions) + + def workspace_id(self): + return self.workspace_role.workspace_id diff --git a/atst/routes/__init__.py b/atst/routes/__init__.py new file mode 100644 index 00000000..1884d28f --- /dev/null +++ b/atst/routes/__init__.py @@ -0,0 +1,61 @@ +from flask import Blueprint, render_template, g, redirect, session, url_for, request +from flask import current_app as app +import pendulum + +from atst.domain.requests import Requests +from atst.domain.users import Users +from atst.domain.authnid.utils import parse_sdn + +bp = Blueprint("atst", __name__) + + +@bp.route("/") +def root(): + return render_template("root.html") + + +@bp.route("/home") +def home(): + return render_template("home.html") + + +@bp.route("/styleguide") +def styleguide(): + return render_template("styleguide.html") + + +@bp.route('/') +def catch_all(path): + return render_template("{}.html".format(path)) + + +@bp.route('/login-redirect') +def login_redirect(): + if request.environ.get('HTTP_X_SSL_CLIENT_VERIFY') == 'SUCCESS' and _is_valid_certificate(request): + sdn = request.environ.get('HTTP_X_SSL_CLIENT_S_DN') + sdn_parts = parse_sdn(sdn) + user = Users.get_or_create_by_dod_id(**sdn_parts) + session["user_id"] = user.id + + return redirect(url_for("atst.home")) + else: + return redirect(url_for("atst.unauthorized")) + + +@bp.route("/unauthorized") +def unauthorized(): + template = render_template('unauthorized.html') + response = app.make_response(template) + response.status_code = 401 + return response + + +def _is_valid_certificate(request): + cert = request.environ.get('HTTP_X_SSL_CLIENT_CERT') + if cert: + result = app.crl_validator.validate(cert.encode()) + if not result: + app.logger.info(app.crl_validator.errors[-1]) + return result + else: + return False diff --git a/atst/routes/dev.py b/atst/routes/dev.py new file mode 100644 index 00000000..cbd02cea --- /dev/null +++ b/atst/routes/dev.py @@ -0,0 +1,58 @@ +from flask import Blueprint, request, session, redirect, url_for + +from atst.domain.users import Users + +bp = Blueprint("dev", __name__) + +_DEV_USERS = { + "sam": { + "dod_id": "1234567890", + "first_name": "Sam", + "last_name": "Seeceepio", + "atat_role": "ccpo", + }, + "amanda": { + "dod_id": "2345678901", + "first_name": "Amanda", + "last_name": "Adamson", + "atat_role": "default", + }, + "brandon": { + "dod_id": "3456789012", + "first_name": "Brandon", + "last_name": "Buchannan", + "atat_role": "default", + }, + "christina": { + "dod_id": "4567890123", + "first_name": "Christina", + "last_name": "Collins", + "atat_role": "default", + }, + "dominick": { + "dod_id": "5678901234", + "first_name": "Dominick", + "last_name": "Domingo", + "atat_role": "default", + }, + "erica": { + "dod_id": "6789012345", + "first_name": "Erica", + "last_name": "Eichner", + "atat_role": "default", + }, +} + + +@bp.route("/login-dev") +def login_dev(): + role = request.args.get("username", "amanda") + user_data = _DEV_USERS[role] + basic_data = {k:v for k,v in user_data.items() if k not in ["dod_id", "atat_role"]} + user = _set_user_permissions(user_data["dod_id"], user_data["atat_role"], basic_data) + session["user_id"] = user.id + return redirect(url_for("atst.home")) + + +def _set_user_permissions(dod_id, role, user_data): + return Users.get_or_create_by_dod_id(dod_id, atat_role_name=role, **user_data) diff --git a/atst/routes/requests/__init__.py b/atst/routes/requests/__init__.py new file mode 100644 index 00000000..5a5a978f --- /dev/null +++ b/atst/routes/requests/__init__.py @@ -0,0 +1,7 @@ +from flask import Blueprint + +requests_bp = Blueprint("requests", __name__) + +from . import index +from . import requests_form +from . import financial_verification diff --git a/atst/routes/requests/financial_verification.py b/atst/routes/requests/financial_verification.py new file mode 100644 index 00000000..38420287 --- /dev/null +++ b/atst/routes/requests/financial_verification.py @@ -0,0 +1,44 @@ +from flask import render_template, redirect, url_for +from flask import request as http_request + +from . import requests_bp +from atst.domain.requests import Requests +from atst.forms.financial import FinancialForm + + +@requests_bp.route("/requests/verify/", methods=["GET"]) +def financial_verification(request_id=None): + request = Requests.get(request_id) + form = FinancialForm(data=request.body.get("financial_verification")) + return render_template( + "requests/financial_verification.html", f=form, request_id=request_id + ) + + +@requests_bp.route("/requests/verify/", methods=["POST"]) +def update_financial_verification(request_id): + post_data = http_request.form + existing_request = Requests.get(request_id) + form = FinancialForm(post_data) + + rerender_args = dict(request_id=request_id, f=form) + + if form.validate(): + request_data = {"financial_verification": post_data} + Requests.update(request_id, request_data) + valid = form.perform_extra_validation( + existing_request.body.get("financial_verification") + ) + if valid: + return redirect(url_for("requests.financial_verification_submitted")) + else: + return render_template( + "requests/financial_verification.html", **rerender_args + ) + else: + return render_template("requests/financial_verification.html", **rerender_args) + + +@requests_bp.route("/requests/financial_verification_submitted") +def financial_verification_submitted(): + pass diff --git a/atst/routes/requests/index.py b/atst/routes/requests/index.py new file mode 100644 index 00000000..7e098b47 --- /dev/null +++ b/atst/routes/requests/index.py @@ -0,0 +1,35 @@ +import pendulum +from flask import render_template, g + +from . import requests_bp +from atst.domain.requests import Requests + + +def map_request(user, request): + time_created = pendulum.instance(request.time_created) + is_new = time_created.add(days=1) > pendulum.now() + + return { + "order_id": request.id, + "is_new": is_new, + "status": request.status, + "app_count": 1, + "date": time_created.format("M/DD/YYYY"), + "full_name": user.full_name + } + + +@requests_bp.route("/requests", methods=["GET"]) +def requests_index(): + requests = [] + if ( + "review_and_approve_jedi_workspace_request" + in g.current_user.atat_permissions + ): + requests = Requests.get_many() + else: + requests = Requests.get_many(creator_id=g.current_user.id) + + mapped_requests = [map_request(g.current_user, r) for r in requests] + + return render_template("requests.html", requests=mapped_requests) diff --git a/atst/routes/requests/jedi_request_flow.py b/atst/routes/requests/jedi_request_flow.py new file mode 100644 index 00000000..e750a9e0 --- /dev/null +++ b/atst/routes/requests/jedi_request_flow.py @@ -0,0 +1,128 @@ +from collections import defaultdict + +from atst.domain.requests import Requests +from atst.forms.request import RequestForm +from atst.forms.org import OrgForm +from atst.forms.poc import POCForm +from atst.forms.review import ReviewForm + + +class JEDIRequestFlow(object): + def __init__( + self, + current_step, + request=None, + post_data=None, + request_id=None, + current_user=None, + existing_request=None, + ): + self.current_step = current_step + self.request = request + + self.post_data = post_data + self.is_post = self.post_data is not None + + self.request_id = request_id + self.form = self._form() + + self.current_user = current_user + self.existing_request = existing_request + + def _form(self): + if self.is_post: + return self.form_class()(self.post_data) + elif self.request: + return self.form_class()(data=self.current_step_data) + else: + return self.form_class()() + + def validate(self): + return self.form.validate() + + def validate_warnings(self): + existing_request_data = ( + self.existing_request and self.existing_request.body.get(self.form_section) + ) or None + + valid = self.form.perform_extra_validation(existing_request_data) + return valid + + @property + def current_screen(self): + return self.screens[self.current_step - 1] + + @property + def form_section(self): + return self.current_screen["section"] + + def form_class(self): + return self.current_screen["form"] + + @property + def current_step_data(self): + data = {} + + if self.is_post: + data = self.post_data + + if self.request: + if self.form_section == "review_submit": + data = self.request.body + else: + data = self.request.body.get(self.form_section, {}) + + return defaultdict(lambda: defaultdict(lambda: "Input required"), data) + + @property + def can_submit(self): + return self.request and self.request.status != "incomplete" + + @property + def next_screen(self): + return self.current_step + 1 + + @property + def screens(self): + return [ + { + "title": "Details of Use", + "section": "details_of_use", + "form": RequestForm, + "subitems": [ + { + "title": "Overall request details", + "id": "overall-request-details", + }, + {"title": "Cloud Resources", "id": "cloud-resources"}, + {"title": "Support Staff", "id": "support-staff"}, + ], + "show": True, + }, + { + "title": "Information About You", + "section": "information_about_you", + "form": OrgForm, + "show": True, + }, + { + "title": "Primary Point of Contact", + "section": "primary_poc", + "form": POCForm, + "show": True, + }, + { + "title": "Review & Submit", + "section": "review_submit", + "form": ReviewForm, + "show": True, + }, + ] + + def create_or_update_request(self): + request_data = {self.form_section: self.form.data} + if self.request_id: + Requests.update(self.request_id, request_data) + else: + request = Requests.create(self.current_user.id, request_data) + self.request_id = request.id diff --git a/atst/routes/requests/requests_form.py b/atst/routes/requests/requests_form.py new file mode 100644 index 00000000..63a14224 --- /dev/null +++ b/atst/routes/requests/requests_form.py @@ -0,0 +1,98 @@ +from flask import g, redirect, render_template, url_for, request as http_request + +from . import requests_bp +from atst.domain.requests import Requests +from atst.routes.requests.jedi_request_flow import JEDIRequestFlow + + +@requests_bp.route("/requests/new/", methods=["GET"]) +def requests_form_new(screen): + jedi_flow = JEDIRequestFlow(screen, request=None) + + return render_template( + "requests/screen-%d.html" % int(screen), + f=jedi_flow.form, + data=jedi_flow.current_step_data, + screens=jedi_flow.screens, + current=screen, + next_screen=screen + 1, + can_submit=jedi_flow.can_submit, + ) + + +@requests_bp.route( + "/requests/new/", methods=["GET"], defaults={"request_id": None} +) +@requests_bp.route("/requests/new//", methods=["GET"]) +def requests_form_update(screen=1, request_id=None): + request = Requests.get(request_id) if request_id is not None else None + jedi_flow = JEDIRequestFlow(screen, request, request_id=request_id) + + return render_template( + "requests/screen-%d.html" % int(screen), + f=jedi_flow.form, + data=jedi_flow.current_step_data, + screens=jedi_flow.screens, + current=screen, + next_screen=screen + 1, + request_id=request_id, + can_submit=jedi_flow.can_submit, + ) + + +@requests_bp.route( + "/requests/new/", methods=["POST"], defaults={"request_id": None} +) +@requests_bp.route("/requests/new//", methods=["POST"]) +def requests_update(screen=1, request_id=None): + screen = int(screen) + post_data = http_request.form + current_user = g.current_user + existing_request = Requests.get(request_id) if request_id is not None else None + jedi_flow = JEDIRequestFlow( + screen, + post_data=post_data, + request_id=request_id, + current_user=current_user, + existing_request=existing_request, + ) + + rerender_args = dict( + f=jedi_flow.form, + data=post_data, + screens=jedi_flow.screens, + current=screen, + next_screen=jedi_flow.next_screen, + request_id=jedi_flow.request_id, + ) + + if jedi_flow.validate(): + jedi_flow.create_or_update_request() + valid = jedi_flow.validate_warnings() + if valid: + if jedi_flow.next_screen > len(jedi_flow.screens): + where = "/requests" + else: + where = url_for( + "requests.requests_form_update", + screen=jedi_flow.next_screen, + request_id=jedi_flow.request_id, + ) + return redirect(where) + else: + return render_template( + "requests/screen-%d.html" % int(screen), **rerender_args + ) + else: + return render_template("requests/screen-%d.html" % int(screen), **rerender_args) + + +@requests_bp.route("/requests/submit/", methods=["POST"]) +def requests_submit(request_id=None): + request = Requests.get(request_id) + Requests.submit(request) + + if request.status == "approved": + return redirect("/requests?modal=True") + else: + return redirect("/requests") diff --git a/atst/routes/workspaces.py b/atst/routes/workspaces.py new file mode 100644 index 00000000..e614c08c --- /dev/null +++ b/atst/routes/workspaces.py @@ -0,0 +1,38 @@ +from flask import Blueprint, render_template + +from atst.domain.workspaces import Projects, Members + + +bp = Blueprint("workspaces", __name__) + +mock_workspaces = [ + { + "name": "Unclassified IaaS and PaaS for Defense Digital Service (DDS)", + "id": "5966187a-eff9-44c3-aa15-4de7a65ac7ff", + "task_order": {"number": 123456}, + "user_count": 23, + } +] + + +@bp.route("/workspaces") +def workspaces(): + return render_template("workspaces.html", page=5, workspaces=mock_workspaces) + + +@bp.route("/workspaces//projects") +def workspace_projects(workspace_id): + projects_repo = Projects() + projects = projects_repo.get_many(workspace_id) + return render_template( + "workspace_projects.html", workspace_id=workspace_id, projects=projects + ) + + +@bp.route("/workspaces//members") +def workspace_members(workspace_id): + members_repo = Members() + members = members_repo.get_many(workspace_id) + return render_template( + "workspace_members.html", workspace_id=workspace_id, members=members + ) diff --git a/atst/sessions.py b/atst/sessions.py deleted file mode 100644 index f7f4dfd8..00000000 --- a/atst/sessions.py +++ /dev/null @@ -1,71 +0,0 @@ -from uuid import uuid4 -import json -from redis import exceptions - - -class SessionStorageError(Exception): - pass - - -class SessionNotFoundError(Exception): - pass - - -class Sessions(object): - def start_session(self, user): - raise NotImplementedError() - - def get_session(self, session_id): - raise NotImplementedError() - - def generate_session_id(self): - return str(uuid4()) - - def build_session_dict(self, user=None): - return {"user": user or {}} - - -class DictSessions(Sessions): - def __init__(self): - self.sessions = {} - - def start_session(self, user): - session_id = self.generate_session_id() - self.sessions[session_id] = self.build_session_dict(user=user) - return session_id - - def get_session(self, session_id): - try: - session = self.sessions[session_id] - except KeyError: - raise SessionNotFoundError - - return session - - -class RedisSessions(Sessions): - def __init__(self, redis, ttl_seconds): - self.redis = redis - self.ttl_seconds = ttl_seconds - - def start_session(self, user): - session_id = self.generate_session_id() - session_dict = self.build_session_dict(user=user) - session_serialized = json.dumps(session_dict) - try: - self.redis.setex(session_id, self.ttl_seconds, session_serialized) - except exceptions.ConnectionError: - raise SessionStorageError - return session_id - - def get_session(self, session_id): - try: - session_serialized = self.redis.get(session_id) - except exceptions.ConnectionError: - raise - - if session_serialized: - self.redis.expire(session_id, self.ttl_seconds) - return json.loads(session_serialized) - else: - raise SessionNotFoundError diff --git a/atst/ui_methods.py b/atst/ui_methods.py deleted file mode 100644 index cc93a14e..00000000 --- a/atst/ui_methods.py +++ /dev/null @@ -1,20 +0,0 @@ -import os -import re - -def navigationContext(self): - return 'workspace' if re.match('\/workspaces\/[A-Za-z0-9]*', self.request.uri) else 'global' - -def dev(self): - return os.getenv("TORNADO_ENV", "dev") == "dev" - -def matchesPath(self, href): - return re.match('^'+href, self.request.uri) - -def modal(self, body): - return self.render_string( - "components/modal.html.to", - body=body) - -def modalOpen(self): - # For now, just check a dummy URL param - return self.get_argument("modal", False) diff --git a/atst/ui_modules.py b/atst/ui_modules.py deleted file mode 100644 index 96bdab07..00000000 --- a/atst/ui_modules.py +++ /dev/null @@ -1,57 +0,0 @@ -from tornado.web import UIModule -# from tornado.template import raw -import re - -class Alert(UIModule): - def render(self, title, message=None, actions=None, level='info'): - return self.render_string( - "components/alert.html.to", - title=title, - message=message, - actions=actions, - level=level) - -class TextInput(UIModule): - def render(self, field, placeholder=''): - return self.render_string( - "components/text_input.html.to", - field=field, - label=re.sub('<[^<]+?>', '', str(field.label)), - errors=field.errors, - placeholder=placeholder, - description=field.description) - -class OptionsInput(UIModule): - def render(self, field, inline=False): - return self.render_string( - "components/options_input.html.to", - field=field, - label=re.sub('<[^<]+?>', '', str(field.label)), - errors=field.errors, - description=field.description, - inline=inline) - -class Icon(UIModule): - def render(self, name, classes=''): - with open('static/icons/%s.svg' % name) as svg: - return self.render_string( - "components/icon.html.to", svg=svg.read(), name=name, classes=classes) - -class SidenavItem(UIModule): - def render(self, label, href, active=False, icon=None, subnav=None): - return self.render_string( - "navigation/_sidenav_item.html.to", - label=label, - href=href, - active=active, - icon=icon, - subnav=subnav) - -class EmptyState(UIModule): - def render(self, message, actionLabel, actionHref, icon=None): - return self.render_string( - "components/empty_state.html.to", - message=message, - actionLabel=actionLabel, - actionHref=actionHref, - icon=icon) diff --git a/config/base.ini b/config/base.ini index 431eacf7..f256fa3a 100644 --- a/config/base.ini +++ b/config/base.ini @@ -2,12 +2,22 @@ PORT=8000 ENVIRONMENT = dev DEBUG = true -AUTHZ_BASE_URL = http://localhost:8002 -AUTHNID_BASE_URL= https://localhost:8001 -FUNDZ_BASE_URL= http://localhost:8004 COOKIE_SECRET = some-secret-please-replace SECRET = change_me_into_something_secret -CAC_URL = https://localhost:8001 -REQUESTS_QUEUE_BASE_URL = http://localhost:8003 +SECRET_KEY = change_me_into_something_secret +CAC_URL = http://localhost:8000/login-redirect +PE_NUMBER_CSV_URL = http://c95e1ebb198426ee57b8-174bb05a294821bedbf46b6384fe9b1f.r31.cf5.rackcdn.com/penumbers.csv REDIS_URI = redis://localhost:6379 -SESSION_TTL_SECONDS = 600 +PGAPPNAME = atst +PGHOST = localhost +PGPORT = 5432 +PGUSER = postgres +PGPASSWORD = postgres +PGDATABASE = atat +SESSION_TYPE = redis +SESSION_COOKIE_NAME=atat +SESSION_USE_SIGNER = True +PERMANENT_SESSION_LIFETIME = 600 +CRL_DIRECTORY = crl +CA_CHAIN = ssl/server-certs/ca-chain.pem +WTF_CSRF_ENABLED = true diff --git a/config/ci.ini b/config/ci.ini index e69de29b..3ee7f480 100644 --- a/config/ci.ini +++ b/config/ci.ini @@ -0,0 +1,6 @@ +[default] +PGHOST = postgreshost +PGDATABASE = atat_test +REDIS_URI = redis://redishost:6379 +CRL_DIRECTORY = tests/fixtures/crl +WTF_CSRF_ENABLED = false diff --git a/config/prod.ini b/config/prod.ini new file mode 100644 index 00000000..fbaaa394 --- /dev/null +++ b/config/prod.ini @@ -0,0 +1,2 @@ +[default] +SESSION_COOKIE_SECURE=True diff --git a/config/test.ini b/config/test.ini new file mode 100644 index 00000000..614cdb7b --- /dev/null +++ b/config/test.ini @@ -0,0 +1,4 @@ +[default] +PGDATABASE = atat_test +CRL_DIRECTORY = tests/fixtures/crl +WTF_CSRF_ENABLED = false diff --git a/deploy/docker/tester/Dockerfile b/deploy/docker/tester/Dockerfile index c490c6ec..5486ffa1 100644 --- a/deploy/docker/tester/Dockerfile +++ b/deploy/docker/tester/Dockerfile @@ -8,6 +8,7 @@ ARG APP_DIR=/opt/atat/atst ARG CIBUILD=true ENV APP_DIR "${APP_DIR}" +ENV FLASK_ENV ci ENV SKIP_PIPENV true # Use dumb-init for proper signal handling diff --git a/ipython_setup.py b/ipython_setup.py new file mode 100644 index 00000000..125a3d2b --- /dev/null +++ b/ipython_setup.py @@ -0,0 +1,9 @@ +from atst.app import make_config, make_app +from atst.database import db +from atst.models import * + +app = make_app(make_config()) +ctx = app.app_context() +ctx.push() + +print("\nWelcome to atst. This shell has all models in scope, and a SQLAlchemy session called db.") diff --git a/js/example.js b/js/example.js new file mode 100644 index 00000000..7cb5b7d1 --- /dev/null +++ b/js/example.js @@ -0,0 +1,4 @@ +window.onload = function() { + console.log('hello from example') +} + diff --git a/js/index.js b/js/index.js new file mode 100644 index 00000000..4f8a3ad3 --- /dev/null +++ b/js/index.js @@ -0,0 +1,5 @@ +import classes from '../styles/atat.scss' + +import './example' + +console.log('hello from index') diff --git a/package.json b/package.json index 5e9a5920..61eddafa 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,19 @@ "description": "ATST Stateless Services", "main": "index.js", "scripts": { + "watch": "parcel watch js/index.js -d static/assets --public-url /static/assets -o index.js --no-autoinstall", + "build": "parcel build js/index.js -d static/assets --public-url /static/assets -o index.js", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "MIT", "dependencies": { "npm": "^6.0.1", - "uswds": "^1.6.3" + "parcel": "^1.9.7", + "uswds": "^1.6.3", + "vue": "^2.5.17" + }, + "devDependencies": { + "node-sass": "^4.9.2" } } diff --git a/script/bootstrap b/script/bootstrap index 2512dde7..e72c4983 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -5,9 +5,6 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Set sass compiling command for this app -COMPILE_SASS_CMD="webassets -m atst.assets build" - # Enable python and node package installation INSTALL_PYTHON_PACKAGES="true" INSTALL_NODE_PACKAGES="true" diff --git a/script/cibuild b/script/cibuild index e9d01564..7af22fea 100755 --- a/script/cibuild +++ b/script/cibuild @@ -5,4 +5,19 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Run lint/style checks and unit tests -source ./script/test +export FLASK_ENV=ci + +# Enable database resetting +RESET_DB="true" + +# Define all relevant python files and directories for this app +PYTHON_FILES="./app.py ./atst ./config" + +# Enable Python testing +RUN_PYTHON_TESTS="true" + +# Compile assets +yarn build + +# Run the shared test script +source ./script/include/run_test diff --git a/script/console b/script/console new file mode 100755 index 00000000..0561ac99 --- /dev/null +++ b/script/console @@ -0,0 +1,9 @@ +#!/bin/bash + +# If a command fails, exit the script +set -e + +# Ensure we are in the app root directory (not the /script directory) +cd "$(dirname "${0}")/.." + +pipenv run ipython -i ./ipython_setup.py diff --git a/script/get_db_settings b/script/get_db_settings new file mode 100755 index 00000000..c96970a8 --- /dev/null +++ b/script/get_db_settings @@ -0,0 +1,8 @@ +#!/bin/bash + +# script/get_db_settings: Fetch postgresql settings and set them as ENV vars + +source "$(dirname "${0}")"/../script/include/global_header.inc.sh + +# Run the shared get_db_settings script +source ./script/include/run_get_db_settings.sh diff --git a/script/include b/script/include index 7417942f..8cf96c97 160000 --- a/script/include +++ b/script/include @@ -1 +1 @@ -Subproject commit 7417942f1614d6a7ad94e94d1621dca9b422dec2 +Subproject commit 8cf96c9776e7fd73c11d57160d26fc1715bf00da diff --git a/script/ingest_pe_numbers.py b/script/ingest_pe_numbers.py new file mode 100644 index 00000000..d8b22059 --- /dev/null +++ b/script/ingest_pe_numbers.py @@ -0,0 +1,33 @@ +from urllib.request import urlopen +import csv + +# Add root project dir to the python path +import os +import sys +parent_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) +sys.path.append(parent_dir) + +from atst.app import make_app, make_config +from atst.domain.pe_numbers import PENumbers + + +def get_pe_numbers(url): + response = urlopen(url) + t = response.read().decode("utf-8") + return list(csv.reader(t.split("\r\n"))) + +def make_pe_number_repo(config): + deps = make_deps(config) + db = deps["db_session"] + return PENumbers(db) + +if __name__ == "__main__": + config = make_config() + url = config['PE_NUMBER_CSV_URL'] + print("Fetching PE numbers from {}".format(url)) + pe_numbers = get_pe_numbers(url) + + app = make_app(config) + with app.app_context(): + print("Inserting {} PE numbers".format(len(pe_numbers))) + PENumbers.create_many(pe_numbers) diff --git a/script/server b/script/server index 47e7cbaa..c03cfdd5 100755 --- a/script/server +++ b/script/server @@ -4,5 +4,8 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh +# Compile js/css assets +yarn build + # Launch the app run_command "./app.py ${LAUNCH_ARGS}" diff --git a/script/setup b/script/setup index 925ced94..23a2fce3 100755 --- a/script/setup +++ b/script/setup @@ -8,5 +8,11 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh # Turn on sass compiler installation INSTALL_SASS="true" +# Enable database resetting +RESET_DB="true" + # Run the shared setup script source ./script/include/run_setup + +# Fetch and import the PE numbers +run_command "python script/ingest_pe_numbers.py" diff --git a/script/sync-crls b/script/sync-crls new file mode 100755 index 00000000..93ec6772 --- /dev/null +++ b/script/sync-crls @@ -0,0 +1,16 @@ +#!/bin/bash + +# script/sync-crls: update the DOD CRLs and place them where authnid expects them +set -e +cd "$(dirname "$0")/.." + +mkdir -p crl-tmp +pipenv run python ./atst/domain/authnid/crl/util.py crl-tmp +mkdir -p crl +rsync -rq crl-tmp/. crl/. +rm -rf crl-tmp + +if [[ $FLASK_ENV != "production" ]]; then + # place our test CRL there + cp ssl/client-certs/client-ca.der.crl crl/ +fi diff --git a/script/sync-dod-certs b/script/sync-dod-certs new file mode 100755 index 00000000..043629c1 --- /dev/null +++ b/script/sync-dod-certs @@ -0,0 +1,25 @@ +#!/bin/bash + +# script/sync-dod-certs: update the CA bundle with DOD intermediate and root CAs + +CAS_FILE_NAME="Certificates_PKCS7_v5.3_DoD" +CA_CHAIN="ssl/server-certs/ca-chain.pem" + +echo "Resetting CA bundle..." +rm ssl/server-certs/ca-chain.pem &> /dev/null || true +touch $CA_CHAIN + +if [[ $FLASK_ENV != "production" ]]; then + # only for testing and development + echo "Copy in testing client CA..." + cat ssl/client-certs/client-ca.crt >> $CA_CHAIN +fi + +# dod intermediate certs +echo "Adding DoD root certs" +rm -rf tmp || true +mkdir tmp +curl --silent -o tmp/dod-cas.zip "https://iasecontent.disa.mil/pki-pke/$CAS_FILE_NAME.zip" +unzip tmp/dod-cas.zip -d tmp/ &> /dev/null +openssl pkcs7 -in "tmp/$CAS_FILE_NAME/$CAS_FILE_NAME.pem.p7b" -print_certs >> $CA_CHAIN +rm -rf tmp diff --git a/script/test b/script/test index 1f6c3380..bd231db8 100755 --- a/script/test +++ b/script/test @@ -4,6 +4,11 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh +export FLASK_ENV=test + +# Enable database resetting +RESET_DB="true" + # Define all relevant python files and directories for this app PYTHON_FILES="./app.py ./atst ./config" diff --git a/script/update b/script/update index 8cb772c1..46d5d549 100755 --- a/script/update +++ b/script/update @@ -4,5 +4,11 @@ source "$(dirname "${0}")"/../script/include/global_header.inc.sh -# Run the bootstrap script -source ./script/bootstrap +# Enable DB migration +MIGRATE_DB="true" + +# Run the shared update script +source ./script/include/run_update + +# Fetch and import/update the PE numbers +run_command "python script/ingest_pe_numbers.py" diff --git a/ssl/certificate-authority/ca.crt b/ssl/certificate-authority/ca.crt new file mode 100644 index 00000000..60ed3ff2 --- /dev/null +++ b/ssl/certificate-authority/ca.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEJDCCAwygAwIBAgIJAK4JGo3BBGhVMA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNV +BAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFuaWExFTATBgNVBAcTDFBoaWxhZGVs +cGhpYTEMMAoGA1UEChMDRG9EMQwwCgYDVQQLEwNERFMxEDAOBgNVBAMTB0FUQVQg +Q0EwHhcNMTgwNjAxMTk0NjIyWhcNMzgwNTI3MTk0NjIyWjBpMQswCQYDVQQGEwJV +UzEVMBMGA1UECBMMUGVubnN5bHZhbmlhMRUwEwYDVQQHEwxQaGlsYWRlbHBoaWEx +DDAKBgNVBAoTA0RvRDEMMAoGA1UECxMDRERTMRAwDgYDVQQDEwdBVEFUIENBMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzYU7UbstArnnVliaC/TB6Vir +kVWMnAEYMUZA1BKP8DZaNEKbzFH2+mMw7O0BY7Ph9x0hEZ1kXLr6U93xcKyUWNPo +13i5EwUUCSh2MdPfS8ZZt8DUIIKC7XzFnKyKSKQmr0Mt9dC44rryPKTBvmI60rQ8 +VZkFEgvs8FCP0M4Ar6/gtJ24ZLEtilu5dQBSlru4nPGXg07r2C2JgEZWshtMBtbH +LkOM2gtp/pkYCCG0zqeU+0s3H8IqDq0uYkONOfVeCumbg1/AtjgrZu7aOVPKyibk +aI6sTTooXE5aSZkfkx0z6+fKM2nPSe30HgiBODtb7G+44ln08d0isjpQ67OvGQID +AQABo4HOMIHLMB0GA1UdDgQWBBSl7CUAWPbx8XqotKKKAufPh0wn4DCBmwYDVR0j +BIGTMIGQgBSl7CUAWPbx8XqotKKKAufPh0wn4KFtpGswaTELMAkGA1UEBhMCVVMx +FTATBgNVBAgTDFBlbm5zeWx2YW5pYTEVMBMGA1UEBxMMUGhpbGFkZWxwaGlhMQww +CgYDVQQKEwNEb0QxDDAKBgNVBAsTA0REUzEQMA4GA1UEAxMHQVRBVCBDQYIJAK4J +Go3BBGhVMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBABguwdFk42YP +8U6Du5HQ6Is1jfc1KEOowdh0d2MCH8q0KNktqiu6kWzjH1gRjRwc07bAkAWqXPB6 +6gkRGYe/FRgi2Rn+Uo5UC5ahI4cXkE8OitCIEP3Br9fUw+vj/3Iiov0QZ6Hv81Kl +ZTZhLiZbjAg5maL/vufnUp+n15qzm67APh3/2hcgO93UlE9o9vXohWy1lHs8u12o +hPLxghSmGc9eKalEWEs61OrohpOtCHUEd1isq76WhaiXSwSUrBxgy89Z517A7ffC +BjzLo5AVo6a9ou+ONVeZk8qw6YR6X9J7axy8YuTWt+Z82WFvOF0ubkqjm72d001M +7R9zCOQ3O+g= +-----END CERTIFICATE----- diff --git a/ssl/certificate-authority/ca.key b/ssl/certificate-authority/ca.key new file mode 100644 index 00000000..529761e9 --- /dev/null +++ b/ssl/certificate-authority/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAzYU7UbstArnnVliaC/TB6VirkVWMnAEYMUZA1BKP8DZaNEKb +zFH2+mMw7O0BY7Ph9x0hEZ1kXLr6U93xcKyUWNPo13i5EwUUCSh2MdPfS8ZZt8DU +IIKC7XzFnKyKSKQmr0Mt9dC44rryPKTBvmI60rQ8VZkFEgvs8FCP0M4Ar6/gtJ24 +ZLEtilu5dQBSlru4nPGXg07r2C2JgEZWshtMBtbHLkOM2gtp/pkYCCG0zqeU+0s3 +H8IqDq0uYkONOfVeCumbg1/AtjgrZu7aOVPKyibkaI6sTTooXE5aSZkfkx0z6+fK +M2nPSe30HgiBODtb7G+44ln08d0isjpQ67OvGQIDAQABAoIBAHR4EInc3UEyQVu5 +knM8Hbgzu+b86FZweFlUSuDkNBYZdz0ukkRUHvb+x3c9SRBLnL8CDv+AhqPWgo6M +tIr6Aofkb4vMqnWQ5y3ZdEIApAa5PZbY/F4AGFql3wdO8H8CJ7ojBCTOSDiVYTnk +1Lcjy9okshyAP1Ne1sPJo/bdB56HtXs+wqok1NntIQwiXjjD9xUuc1EZk0J4M97L +vBUjUGNX942UjtRiey5zwhRp3bTPasTduHcA01NaIbOVYlRFwc2W+cflz0l6ml2p +14TNEEvIMMMCNKnlPrpGI23n0psAvE4nbuxZQGVYAFvXrWn+Gyvz0Yag2EoMUCEs +ziLED9ECgYEA6IByu+xqIuIAhj/PwIIxV4+lkuV4TXIlfAFLR4JuokOVfbRsmu2e +9EfeOUD9LfQ4KsG5mu4Abpja0k/VKRKRGRjV6Oe2C6VK942HFP6Kpn0hgIuomZkD +eVv8naDezZjAvVace38zjRWB2GXTpapwBAgf/YflPPsDZ8bi/weqZCMCgYEA4kqx +Ka489Rr7+cSXpMeS5lLufhlaE5OVQc5HVFREDAI5vXU8BM2sLiHTC/BHjis2JvLm +aRJ0UsxUoIUURl2KjTbx3zns4HDVkzBrSpoDXWxBjAo0oEg7JVc+6+qEqbDHHS1L +/UJ6mlUegsE42MkFWG3YJQuHxyLZqPXIwNAyhZMCgYEA5cxnGnSt5rJoAEi7xzMn +H7s71Hf3stw6TlldFV3GiZyw+aDFo09vR1RtQTuJwczbYu88yvOn+6gax7neHo1a +WmrgqiWzGcmS0iDRPZ/kXG/bGBlxV/cTpvSTNx0UejMbdUhQvANaaXyzbLYgPWK6 ++lEphUW2/tG+aOj73UOvVu8CgYA5L8sJz4CUKJeZDTeNauoSzs56i4mZ/OfxU2Hv +S8ROjJlu6ZubUya6Gc4t7DEJGp56xVO5JfLDoeOZFUiEZ8tF2KbTVN4p8hnnMotK +tRU4nM0LyOB3yQk5bIz4LbIM+CG5m+LiQ9Sb//rP7GijUFnLeSbwZbOQfZwn+MUd +BQBfhQKBgQDmuX8tJdPkjE133IhQhZHbHHt6AEQA3aXkFdvPvbYD9VbGTZ8wnpFO +VJrDDWnIKAgO2FerIX9oq+H9a5fggYtTMeAX1cOA6b9SnLmFjt0utxrQKxf7p5I+ +n+EsmcAWfb+KRQwoB0L/mE9Ool14AeJ15kHyNIrCrMPv0J4zoC0Jdg== +-----END RSA PRIVATE KEY----- diff --git a/ssl/certificate-authority/ca.srl b/ssl/certificate-authority/ca.srl new file mode 100644 index 00000000..a23185d3 --- /dev/null +++ b/ssl/certificate-authority/ca.srl @@ -0,0 +1 @@ +F4D74F1607DD3C83 diff --git a/ssl/client-certs/README.md b/ssl/client-certs/README.md new file mode 100644 index 00000000..10ab5fd3 --- /dev/null +++ b/ssl/client-certs/README.md @@ -0,0 +1,30 @@ +Right now, we have two client certificates: + +- atat.mil.crt: beautiful, good, works great +- bad-atat.mil.crt: banned, very bad, is on the CRL + +I more or less used [this article](https://access.redhat.com/documentation/en-us/red_hat_update_infrastructure/2.1/html/administration_guide/chap-red_hat_update_infrastructure-administration_guide-certification_revocation_list_crl) to generate the CRL. Note that I departed from it slightly and used a variation on the openssl config recommended by the ca man page (`man ca`). + +I added the new crl: + +``` +openssl crl -inform pem -in ssl/client-certs/client-ca.crl -outform der -out crl/simon.crl +``` + +Running the scripts verifies that the good one is good and the bad one is bad. + +We can also verify with OpenSSL. First concatenate the CA Bundle and the CRL: + +``` +cat ssl/server-certs/ca-chain.pem ssl/client-certs/client-ca.crl > /tmp/test.pem +``` + +Verify the certs: + +``` +openssl verify -verbose -CAfile /tmp/test.pem -crl_check ssl/client-certs/bad-atat.mil.crt +> error 23 at 0 depth lookup:certificate revoked +openssl verify -verbose -CAfile /tmp/test.pem -crl_check ssl/client-certs/atat.mil.crt +> atat.mil.crt: OK +``` + diff --git a/ssl/client-certs/atat.mil.crt b/ssl/client-certs/atat.mil.crt new file mode 100644 index 00000000..59dcb67f --- /dev/null +++ b/ssl/client-certs/atat.mil.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDqTCCApECCQCoSzDcVuoXYzANBgkqhkiG9w0BAQsFADCBjTELMAkGA1UEBhMC +VVMxFTATBgNVBAgTDFBlbm5zeWx2YW5pYTEVMBMGA1UEBxMMUGhpbGFkZWxwaGlh +MRAwDgYDVQQKEwdGYXV4RG9EMQswCQYDVQQLEwJQVzERMA8GA1UEAxMIRmF1eCBE +b0QxHjAcBgkqhkiG9w0BCQEWD2ZhdXhkb2RAZG9kLmNvbTAeFw0xODA3MjQyMDM0 +MDJaFw0xOTA3MjQyMDM0MDJaMIGeMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVu +bnN5bHZhbmlhMRUwEwYDVQQHEwxQaGlsYWRlbHBoaWExDDAKBgNVBAoTA0RvRDEL +MAkGA1UECxMCUFcxITAfBgNVBAMTGEFSVC5HQVJGVU5LRUwuMTIzNDU2Nzg5MDEj +MCEGCSqGSIb3DQEJARYUYWdhcmZ1bmtlbEBzYW5kZy5jb20wggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQDCRftouylCKDN9GoKRJMWA3gnfEshRxi4P1xU9 +xm0qgPIzTpeZCNUcDbSQzovXQ58ElrDTdUeMv0OV/RLOnNFKgPSAd2f1F4BE1rJR +WHLFjG6mPj769Wl1BhGAwOY/zdhfHYjTKZSApUfP6MuKsD2nciOnJFlqJ439R4LC +S8Fv3RnnKMQlSTMiudOMhtzr8v1poDlxVzu9IF7i/MZKCBFz3e1G2LFIr5ZL+djg +4rsI4lNPVNt1sRiXy/+kltBY8RIbPPP70iT+zmrr6PmEeDSwDSKgW+TBCGK3yFCr +kPXjMZhWOt+7eLanL2KJNrohEkJFzI3tb7zVm6zg5SC1GTIFAgMBAAEwDQYJKoZI +hvcNAQELBQADggEBAKm4W2mAqtRUpwCstCqJCdoOsIgW9pZKTczLERbODHvbfXZA +MfGGnYQiuoOddu9K9UJQIHZLMUYmF9gj9HdY60ttNWeH5XRXIXn6t1Pn8W7q042Q +RqeJ/uOtNG1UXRtHQhK1j73xD3ZSTGw7rTIA2qDgRQMp1h28405kZIiNVRFdNjFh +irAvtQkIXWhIGSr/Lwop98RmTsV17v4iK14Uf2i5QUjdIECiGqGSlk9Jmj8dajzN +cSarkhWDuQmlCplF1lTNcXenC66d1bE/KXb3dEGg+h99KfZVw1+9c5DbWag6IVgG +Xts4GcPhuiKF/pJWRO11L2CfyCveoGM9Osz/vvc= +-----END CERTIFICATE----- diff --git a/ssl/client-certs/atat.mil.csr b/ssl/client-certs/atat.mil.csr new file mode 100644 index 00000000..79695986 --- /dev/null +++ b/ssl/client-certs/atat.mil.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC5DCCAcwCAQAwgZ4xCzAJBgNVBAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFu +aWExFTATBgNVBAcTDFBoaWxhZGVscGhpYTEMMAoGA1UEChMDRG9EMQswCQYDVQQL +EwJQVzEhMB8GA1UEAxMYQVJULkdBUkZVTktFTC4xMjM0NTY3ODkwMSMwIQYJKoZI +hvcNAQkBFhRhZ2FyZnVua2VsQHNhbmRnLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMJF+2i7KUIoM30agpEkxYDeCd8SyFHGLg/XFT3GbSqA8jNO +l5kI1RwNtJDOi9dDnwSWsNN1R4y/Q5X9Es6c0UqA9IB3Z/UXgETWslFYcsWMbqY+ +Pvr1aXUGEYDA5j/N2F8diNMplIClR8/oy4qwPadyI6ckWWonjf1HgsJLwW/dGeco +xCVJMyK504yG3Ovy/WmgOXFXO70gXuL8xkoIEXPd7UbYsUivlkv52ODiuwjiU09U +23WxGJfL/6SW0FjxEhs88/vSJP7Oauvo+YR4NLANIqBb5MEIYrfIUKuQ9eMxmFY6 +37t4tqcvYok2uiESQkXMje1vvNWbrODlILUZMgUCAwEAAaAAMA0GCSqGSIb3DQEB +BQUAA4IBAQCvnKvR8agOyJmLFcrROWGWLdGsr6CFmkcQe1eJ2GFP9XsIbuIjxssn +K2yEK1hY6BAAPl76Arh3WkHOXVQjuzW3hlsu+uwKJnYDecG3I9btP+NkPNyKWrbr +S2GIqa71oKadncV/P9DKsc2+KL2BFo8+IbvwVSPGj63JlJh2T9JFPeAqxeKCUiuO +ac+dgxNtMQRSEYwE1kgdaJu5yRBfepZaeNGJ2KjCivQdsgnlVllPCNwtjciIRLWl +UBdt8kh6Dx0RVIkck5fViFiJodxbfw9filjYITgRuANEJHytNzo3ChsWflZ0UYi/ +j8jAvoqL2d+D/a2ijaxlQeCqu5MUB4wR +-----END CERTIFICATE REQUEST----- diff --git a/ssl/client-certs/atat.mil.key b/ssl/client-certs/atat.mil.key new file mode 100644 index 00000000..5fc2040f --- /dev/null +++ b/ssl/client-certs/atat.mil.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEAwkX7aLspQigzfRqCkSTFgN4J3xLIUcYuD9cVPcZtKoDyM06X +mQjVHA20kM6L10OfBJaw03VHjL9Dlf0SzpzRSoD0gHdn9ReARNayUVhyxYxupj4+ ++vVpdQYRgMDmP83YXx2I0ymUgKVHz+jLirA9p3IjpyRZaieN/UeCwkvBb90Z5yjE +JUkzIrnTjIbc6/L9aaA5cVc7vSBe4vzGSggRc93tRtixSK+WS/nY4OK7COJTT1Tb +dbEYl8v/pJbQWPESGzzz+9Ik/s5q6+j5hHg0sA0ioFvkwQhit8hQq5D14zGYVjrf +u3i2py9iiTa6IRJCRcyN7W+81Zus4OUgtRkyBQIDAQABAoIBAQC0+nSmsBRTaRfu +J1AS3mqPDkmr4ddzNmeaogdLsRnpSo5WdZSMH8pHhAz+CSwEsR3mLGs10j+BQnw3 +sbZfe38NJOyg8JuLmwUHG+qqFPd2SMibXclWCGDhf3G2u/zC24QBt4XLESUiYtZv +PLLA1EXbQ10rS5VwasC/fmq1jdT52yEi4viXdMOSfjYCWg+xIwBsyCQs/lWLsqWD +ZKLYfUAFsYqQ1Axz96yiscgNfPfoPRMoTvU3TuQlGhiQ1ygG5f4xlLEuHXpj1yWw +/liSZVq/a+WQlVAKdlA4IXiC8szPagNSa/beEaj3R+ifoCad5hp/Fsj2JQlHmm30 +D8PAAVFRAoGBAPnRytHsicCuqck0oa2c2nE7gExrZhrO+rZoDHPBXjQiTFstil8r +wK1OCjeeX9TV18szPhkimCVel+goNhSmW4n3BcAM1HTFdZlKY7dwVN/tvtl852Sw +gVhGd3kFDkjUBTlK7W+IW7dzW3KwoSbcBpPRtIX9kKR5Braek4h4pUv3AoGBAMcU +ZMqlHB6k1HH+3bZhyTk1BBAF2PcocqOkI9ahSQjDmVGMSa+nVxC7qE0l+hRRpaFd +Ck6zn41p87Yos1nwNwOBcT3AIk0CNYGTJXJQQnkVzjB2yTdKDC/nAH++WOE2daw6 +0n1kIygOeL6na6r+jCQbsmwmORlqZ1nLPjCIPlrjAoGASpNiJICkLqz1amcXzKgC +XcMRbb6x4FbhaQpujS+wW4fRm3Zg1EBPaGzfh/LzUKn1nWdSplY5bQ5r8pXubwOq +V+kyAj7SPXmkvXoDgoM6Ew755hrvSJOYSS3gBHSJ6xu/43aGosDmAEGjjv1DXkJY +hFAZv9YOE8s9Qc7c4+SAE8kCgYEAm+JPLhJtW11r8LtF9orJWt81iCpcAuSMJ7De +UzDFlHQ8uIsmI8Hfvf2DQq2rDYAFNr441Pl3xO6i5A8oqRMcsMUJ2/V3pl9FcGm9 +F67a7h9x7acF1iJIOrYiQOTWibrwF2WT7pWbpcD3MSq9dw6Mw7VgV6jyawFTXg90 +aeI1GUsCgYEA2/7tNN0Of5W/Ff/2lm9ePhYsZSr+9NoBBQvai7+m5qpSzvoE304Q +1qPW+T5pA4Da34nG+fGJMop0QX9rRTdyE9Ct++8ybIdLFAf35fDxgciohkziji8+ +0BHK7f+GqTDF+KoIZDZYPQgJX17/h8XNtBBSbP7WX8WZHIco/0BtOrc= +-----END RSA PRIVATE KEY----- diff --git a/ssl/client-certs/bad-atat.mil.crt b/ssl/client-certs/bad-atat.mil.crt new file mode 100644 index 00000000..8923a87a --- /dev/null +++ b/ssl/client-certs/bad-atat.mil.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDljCCAn4CCQDe7V0Kcecn2TANBgkqhkiG9w0BAQUFADCBjTELMAkGA1UEBhMC +VVMxFTATBgNVBAgTDFBlbm5zeWx2YW5pYTEVMBMGA1UEBxMMUGhpbGFkZWxwaGlh +MRAwDgYDVQQKEwdGYXV4RG9EMQswCQYDVQQLEwJQVzERMA8GA1UEAxMIRmF1eCBE +b0QxHjAcBgkqhkiG9w0BCQEWD2ZhdXhkb2RAZG9kLmNvbTAeFw0xODA2MjAyMDQz +MTlaFw0xODA3MjAyMDQzMTlaMIGLMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVu +bnN5bHZhbmlhMRUwEwYDVQQHEwxQaGlsYWRlbHBoaWExDDAKBgNVBAoUA1MmRzEe +MBwGA1UEAxMVU0lNT04uUEFVTC4zODU2MTM1OTAxMSAwHgYJKoZIhvcNAQkBFhFz +aW1vbkBzX2FuZF9nLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKao36qwC9Sk5hMujFQm5h7B6WoRFqbWpTw7VSAZeW2ykwWbOBmsEAfgOJ+ctyHq +oMG0S23zJxSkfjO1PLXvu9r1ML0zXtm0uUiTJOMEMyrUBbfCV8zJ3TMuA7voWLi7 +QKsXh1bHdDIXbYP6dLC3w3CnBnr9VihzLth5KLEpz9ePX5gZljHVGldNY4ZR3UbD +IeL7GD0z/jdcNuHxLYsI9gnnfxrOx8LmzDHDwTNsvKYNRjkdu+pja0ojDrE3T61g +nKrWQsDwP9T7v27AfhrF1sxy+5K3YiQkDGtbvwFtKBIG3DJBw8qAqEPbtXw9FpYt +7p8Ti/QYM5SGr/+w3yOgvrkCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAgVarfkoj +YtZ4X/uNzaSTYO10nyPblebmCGdJW4Cwgk7tcyB+ufLKPrWaC0+Y6XPZwCkAM8UF +KqwYVnMWTkYdUI2ff1vst9tZRiANGXuQLgbdGAP2TrcBk/N5Glm6J4wrpT5VAXjR +gBeVxMIWkGb5geDXISJujzrQU26roxEm3F4oUwvAgvMQd/Ha/pzXioaLycc0k91J +apCafD39u5A+X/Y4QG/GfLG0kqOS2ioJDIlb+EJRzIL7s4cvv530p+VLu+AYEgKx +MmGOnmML3qO/+oeL3Y32TP4Hzm2asNScseoi8a1ygyV88rLjLaVrsj7CFp9zJL0O +Ksoovip0wuSVdQ== +-----END CERTIFICATE----- diff --git a/ssl/client-certs/bad-atat.mil.csr b/ssl/client-certs/bad-atat.mil.csr new file mode 100644 index 00000000..ecd99873 --- /dev/null +++ b/ssl/client-certs/bad-atat.mil.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC0TCCAbkCAQAwgYsxCzAJBgNVBAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFu +aWExFTATBgNVBAcTDFBoaWxhZGVscGhpYTEMMAoGA1UEChQDUyZHMR4wHAYDVQQD +ExVTSU1PTi5QQVVMLjM4NTYxMzU5MDExIDAeBgkqhkiG9w0BCQEWEXNpbW9uQHNf +YW5kX2cuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApqjfqrAL +1KTmEy6MVCbmHsHpahEWptalPDtVIBl5bbKTBZs4GawQB+A4n5y3IeqgwbRLbfMn +FKR+M7U8te+72vUwvTNe2bS5SJMk4wQzKtQFt8JXzMndMy4Du+hYuLtAqxeHVsd0 +Mhdtg/p0sLfDcKcGev1WKHMu2HkosSnP149fmBmWMdUaV01jhlHdRsMh4vsYPTP+ +N1w24fEtiwj2Ced/Gs7HwubMMcPBM2y8pg1GOR276mNrSiMOsTdPrWCcqtZCwPA/ +1Pu/bsB+GsXWzHL7krdiJCQMa1u/AW0oEgbcMkHDyoCoQ9u1fD0Wli3unxOL9Bgz +lIav/7DfI6C+uQIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAHQg3idmnhAX9CyO +xbzfrTQ989vs110lTRh8VY+64ufkS2bxGO4fQik+VfSi9wFshTGaUlhtgiBrdfAt +9udaQprWmZabBmiDnoUWiM5srJfYHL5yytrYynwpVe7Y3kPvPT/Zd+B9NBr+G0aq +SxIDce7236vAcjocgCv8gmkdrfkpOTR87gx5q3b1BBv/we4+dUKysloC1Aw23/de +Fi49SH9Xt8ZWUBsW5MesrmTfCXPTauYgYRt8bKtA0qvzzmiE5Ydihpi9HilGuCMr +2LKBQETR6m4FgNXNcsRIlqPR+EY8llTYMEu7LvvHn2RmVpeIT2v5TADV0AighQyB +++ZbkbE= +-----END CERTIFICATE REQUEST----- diff --git a/ssl/client-certs/bad-atat.mil.key b/ssl/client-certs/bad-atat.mil.key new file mode 100644 index 00000000..1c655bef --- /dev/null +++ b/ssl/client-certs/bad-atat.mil.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpgIBAAKCAQEApqjfqrAL1KTmEy6MVCbmHsHpahEWptalPDtVIBl5bbKTBZs4 +GawQB+A4n5y3IeqgwbRLbfMnFKR+M7U8te+72vUwvTNe2bS5SJMk4wQzKtQFt8JX +zMndMy4Du+hYuLtAqxeHVsd0Mhdtg/p0sLfDcKcGev1WKHMu2HkosSnP149fmBmW +MdUaV01jhlHdRsMh4vsYPTP+N1w24fEtiwj2Ced/Gs7HwubMMcPBM2y8pg1GOR27 +6mNrSiMOsTdPrWCcqtZCwPA/1Pu/bsB+GsXWzHL7krdiJCQMa1u/AW0oEgbcMkHD +yoCoQ9u1fD0Wli3unxOL9BgzlIav/7DfI6C+uQIDAQABAoIBAQCJUEiAzO3idT7v +fQG38BjYLLLRZmUAb4fS2Zvoh7SpsmE6VEpjtIW8x3w/3hJxSmzLTG59l8KSWnl0 +xxXPXUetPym6KZIz05h5eGsC9Jnn5qsTXXeTzpqHKZmAAA7hnb7JeOhUkp9lCjJ8 +dCYi2DWaIrPPL94GE+j8CM+DMM0Db9QmShQC5XbZPgsHiHvvffuvd4G90XcANEM/ +KHuwSoZ9xgySZDG+ENlqYu93GGrL3DYUozjMUChzVKZYyYySxII1ja11oznXcAyG +nj5xeBmKv6KzYD5LOMIapWfVTNHLG1FM7bhVccrWKIAVKW4Lqd+gcMC+/wU2YIx9 +K9WGV8RlAoGBANWTrGCvaM9r2piXlGB6VB/KmZXFI9R7wjE+waW+3XBZ6YVZiMGQ +jebeT+PPbeaggaDMIxZ70vJ+rNbS2MYrI44AIIueq636PoT7JtjfhakgZ7LBqc37 +F56rvObPTuFCElVKS1/nIaNAnvoNUoSqt42t7+VzkNfLYCalkHHpsXxHAoGBAMfD +eUhuUaPTDT02NVjrNAA0yIkRIoyrbv7KGKuJStoPy7W4L6aZC0iFWZmwXTYBuC73 +ulZQ88X3bexKS0NkfQJBLPTQFYNUYS/H+OCwkuFj160tysZbG8rx/IsfZwWqoitH +wR1Bgz++k5AApcgjMEWmt8l0NT5Mr6M0waylWGz/AoGBALQa3giCo14XU7XOTZ+2 +SO6uSSoVnwt2eeJRS7fb5pzyFY0QXdTtc9y2qKQxrjoILIhO3V/+d3tq+5IFKCyl +AEylKszSt2/1UXeO28mTZQGkhA4oZmt/TQHPTXNOavRmZVNrXXi4TpN+0RGI3odl +93gQr/bMp95ycNjmUZLeQX/NAoGBAI6PT5SDNjwFuCMA9p1YbSnggWRgGBnvliy6 +qVRxjDuGnkg3A7qO6eB9We42UK7kFz9dh1tmNjIHXCkO9BtKMXRUcvLbNR8eLqVc +vp4LJSc4i4iJb3aTOohgnWvjozAGD+l3MbfhMvtg1AomjCkCA8cRLYPVLNIjBA0i +7zx4W1ydAoGBAKS26yBJT9ZbIKLtoqZ6wOdz0l4r+ZaHmO+LjiGuFUh7w2s2MsPR +Q1JwE5aXaXP9gY7md/gz7Fcm3ebjwRkdcvGvIQyncv4mF64b+FFnpgjQFHg5+OqD +A57e0VDFI2LYhFstVHNZ1sRA+tBKQygd7Hzlz4BZdSD6EY7fvWNSJ7/j +-----END RSA PRIVATE KEY----- diff --git a/ssl/client-certs/client-ca.crt b/ssl/client-certs/client-ca.crt new file mode 100644 index 00000000..80007c82 --- /dev/null +++ b/ssl/client-certs/client-ca.crt @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIElTCCA32gAwIBAgIJAN5qDki+VlfPMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYD +VQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZhbmlhMRUwEwYDVQQHEwxQaGlsYWRl +bHBoaWExEDAOBgNVBAoTB0ZhdXhEb0QxCzAJBgNVBAsTAlBXMREwDwYDVQQDEwhG +YXV4IERvRDEeMBwGCSqGSIb3DQEJARYPZmF1eGRvZEBkb2QuY29tMB4XDTE4MDYy +MDIwMzg0N1oXDTE5MDYyMDIwMzg0N1owgY0xCzAJBgNVBAYTAlVTMRUwEwYDVQQI +EwxQZW5uc3lsdmFuaWExFTATBgNVBAcTDFBoaWxhZGVscGhpYTEQMA4GA1UEChMH +RmF1eERvRDELMAkGA1UECxMCUFcxETAPBgNVBAMTCEZhdXggRG9EMR4wHAYJKoZI +hvcNAQkBFg9mYXV4ZG9kQGRvZC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDyQUFcuQ+YKOEJtv4XjKOTpOLp8IdbsaFwU8YgenMdvAc1ONZRL/2o +jaCZx+kB2QSCVH2jaLUQ/2i4uz4rE21Ngpx+EHa1hgDQANle3d5CWrn2Q10/pdPe +rJHYkMSiZ3cNWfFPBfHDtJrLlRUwJkgy+lUSLnOaipmBZMYXbV8/qUh69nWJQNXi +AvmSUw8jwUPfTrpQVzftkOYz+0HVJyvKijTsj1LaPZTR3D8OhbFnvZWIlhIUjJZO +jap/xQ3YEOcNF+gfx8hDQG2SnltWgecPsgiBRXmZK2IqDv39DE2DNiukEclZLhbN +SpTibNZwkVzcTSRV2mSOHKXqTcH0wTvpAgMBAAGjgfUwgfIwHQYDVR0OBBYEFAo/ +6auHcKMK1ItTElg1Kk4MyoB5MIHCBgNVHSMEgbowgbeAFAo/6auHcKMK1ItTElg1 +Kk4MyoB5oYGTpIGQMIGNMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZh +bmlhMRUwEwYDVQQHEwxQaGlsYWRlbHBoaWExEDAOBgNVBAoTB0ZhdXhEb0QxCzAJ +BgNVBAsTAlBXMREwDwYDVQQDEwhGYXV4IERvRDEeMBwGCSqGSIb3DQEJARYPZmF1 +eGRvZEBkb2QuY29tggkA3moOSL5WV88wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B +AQUFAAOCAQEAp4fVYeSKYJICBQt37NOF6qZ+dv8GBDI+oZy7vC+VcjiRaODkiz9w +IO5dBZxx/ldH5sD24Oc2SH+48S6UjE/D5kDpM/nIddfVfL2f222sE14RsqgrhmbG +qRaEB8NXWiSQyKOKX63v8scioUqb9hFY+gtwb8HDFiOZFx+67L/NaXSh6VA8BbLj +o55EafjTgr+Yad7SrZI5f6Q2iQ+uuHcJsf7fEe3Kts5Uwt5KXBBfMxeaSyQRxNX+ +JBBmy6MaxddPtus3MH+eIgI2Wp2rofH/PtGnSoizBj5IZXBkc18x1DG5pAJL4205 +EKQoicsafE27XBw45dK3cRBLXPWt8JrCBg== +-----END CERTIFICATE----- diff --git a/ssl/client-certs/client-ca.der.crl b/ssl/client-certs/client-ca.der.crl new file mode 100644 index 00000000..8ec9e37f Binary files /dev/null and b/ssl/client-certs/client-ca.der.crl differ diff --git a/ssl/client-certs/client-ca.key b/ssl/client-certs/client-ca.key new file mode 100644 index 00000000..dc6229c6 --- /dev/null +++ b/ssl/client-certs/client-ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA8kFBXLkPmCjhCbb+F4yjk6Ti6fCHW7GhcFPGIHpzHbwHNTjW +US/9qI2gmcfpAdkEglR9o2i1EP9ouLs+KxNtTYKcfhB2tYYA0ADZXt3eQlq59kNd +P6XT3qyR2JDEomd3DVnxTwXxw7Say5UVMCZIMvpVEi5zmoqZgWTGF21fP6lIevZ1 +iUDV4gL5klMPI8FD3066UFc37ZDmM/tB1Scryoo07I9S2j2U0dw/DoWxZ72ViJYS +FIyWTo2qf8UN2BDnDRfoH8fIQ0Btkp5bVoHnD7IIgUV5mStiKg79/QxNgzYrpBHJ +WS4WzUqU4mzWcJFc3E0kVdpkjhyl6k3B9ME76QIDAQABAoIBAQCC7bnBv1MqTY2y +jnAtkhkmRstM3G6LpCk4aE6AZy2oOGM85IcQQfu6CTFva5gHI59IQRnWI1UY5rFW +hfxHk6xTY+/oQkWmPdJamNriZs8k1ZwD+MyBBcLIakQ446UikQDK+n1s1C2iNA4l +UWGuMEJ9KsanmOtp7tagFDLrnnUIFgyfQv5JI/QBZSMd9UReRv3xQrdv+KK58zJE +/zsuFFO00YS0xzDYwikuwabDXaWCt8/9rDDlthIEaJRzTxZiLK90k6DaywRnO7rJ +Q4Q/1WUGzdA7wfkQOWLozP1To2d6Q/KK1TiRaY0uieGvTvT7kXVDne4+lb3zAmAW +IxdyNYBxAoGBAPtgEjGapRzPLcgJqVuup5W+/gc8NWcSK4NJWAwFWN9n6wOf+jQu +YkwVUoF0KN0g9a1rymvnv+fHdvqQ+uDtdqCMcU3DNVx1uwTf0V/kPsxSwhTjrQ3h +4tMXL4EzOUhYV1us/PtrmSlKS1SuQXbBdgNM7n71X0zWgsHeDvIf4YQTAoGBAPa2 +OqNOUFiA8Yz7wG/Aw1LiPX+DJZVmH05yXDSWicwSyrhorxktweMNd1e+syYW+5Qe +GFu3qaxmOlPL9M5IvbUiAV7nmiVcezBnLxBLmOdc9rk8CU8qakZDESsy/pC741/U +y6MQZzsbKIhxG4djbl+9Mr8wom+DGQtkFJ7RvqeTAoGBAOrJRLUIGAfcioo4W/LC +Isz+4w2m8soecn3hV1eC9wtTaHKuTWfHmxAtKi63bCN90Xn1H8/BWcEG0N4f4/OK +WC6Efp9/IKwHWnKnCkxiRzVYZuZT8SLyRIWdNkWarnof6Rg7bt72FMw4FDw3tfVR +pQRYKrpyPFzsTpz850DG/j/5AoGAZ5BxpxH96lkejRc1XfQmSknMlRWBlmiLJcwd +5rl22OLelHDlaAVsSZriiUP1Qj0NmMzVXtMHd+Zl/70zY9DnSf0fZC6G574dvGDk +QcvqQN0mePW51rCwchQ/RcofULR+q0DRxv7gxtAMwNHyQ3A66herENUiqvr2bXCy +s0TK6t8CgYEA7IS8e3x9SvXwfjGyJslbxhI4P7cBuVU5aL1SqYpaNx61JdmnPct4 +ruQntKHL5DvPNNRwFUvySkH93zjvjOWqF1g8kSO2ZPDj+WajStAHwA1TmVYIfkpV +xfv5mlcKUfyLmoJ6nKuCf/pt49Gmp3vRsmxZrEcbBqGAVBI7LslQQr4= +-----END RSA PRIVATE KEY----- diff --git a/ssl/client-certs/client-ca.pem.crl b/ssl/client-certs/client-ca.pem.crl new file mode 100644 index 00000000..d4110181 --- /dev/null +++ b/ssl/client-certs/client-ca.pem.crl @@ -0,0 +1,13 @@ +-----BEGIN X509 CRL----- +MIIB8jCB2zANBgkqhkiG9w0BAQQFADCBjTELMAkGA1UEBhMCVVMxFTATBgNVBAgT +DFBlbm5zeWx2YW5pYTEVMBMGA1UEBxMMUGhpbGFkZWxwaGlhMRAwDgYDVQQKEwdG +YXV4RG9EMQswCQYDVQQLEwJQVzERMA8GA1UEAxMIRmF1eCBEb0QxHjAcBgkqhkiG +9w0BCQEWD2ZhdXhkb2RAZG9kLmNvbRcNMTgwNzMwMjEyOTAxWhcNMTgwODI5MjEy +OTAxWjAcMBoCCQDe7V0Kcecn2RcNMTgwNjIwMjA0NjExWjANBgkqhkiG9w0BAQQF +AAOCAQEAfZSS51Axnx04iSfMd1k5/TvH1R6NvUM20S/rZjJYt/uLqRElnJd7R7aI +lLQQzSdbsuHm8HcfcMS7ZUMv989chKXMbPml+ZXkK/zp7LdjaL5THs09ek0NOM2l +yhJcdE3K5bntk6qSgbsUpBOWLHzrp20is3BPl6gY+JRb0nnZ/SXTr4zfDctGfcot +fSAGs3QA0Q/dpJOlSkGzxlzjB7dXDuoHTaJwy2s48IriNvvtVktM2AS+B/843vMC +ToI5ZUh3RkSCgGvKexobg85Ke1QwWTYuj392JhakpIu/Qc71BK0jtbY9mVuFLwqW +RFXDKIzRiL4S7iZWu/bpqTYyqmCmeA== +-----END X509 CRL----- diff --git a/ssl/client-certs/crl_openssl.conf b/ssl/client-certs/crl_openssl.conf new file mode 100644 index 00000000..5c061883 --- /dev/null +++ b/ssl/client-certs/crl_openssl.conf @@ -0,0 +1,26 @@ +[ ca ] +default_ca = CA_default # The default ca section + +[ CA_default ] + +dir = ./ # top dir +database = $dir/index.txt # index file. +# new_certs_dir = $dir/newcerts # new certs dir + +default_days = 365 # how long to certify for +default_crl_days= 30 # how long before next CRL +default_md = md5 # md to use + +policy = policy_any # default policy +email_in_dn = no # Don't add the email into cert DN +name_opt = ca_default # Subject name display option +cert_opt = ca_default # Certificate display option +copy_extensions = none # Don't copy extensions from request + +[ policy_any ] +countryName = supplied +stateOrProvinceName = optional +organizationName = optional +organizationalUnitName = optional +commonName = supplied +emailAddress = optional diff --git a/ssl/client-certs/index.txt b/ssl/client-certs/index.txt new file mode 100644 index 00000000..ada74bef --- /dev/null +++ b/ssl/client-certs/index.txt @@ -0,0 +1 @@ +R 180720204319Z 180620204611Z DEED5D0A71E727D9 unknown /C=US/ST=Pennsylvania/L=Philadelphia/O=S&G/CN=SIMON.PAUL.3856135901/emailAddress=simon@s_and_g.com diff --git a/ssl/client-certs/index.txt.attr b/ssl/client-certs/index.txt.attr new file mode 100644 index 00000000..8f7e63a3 --- /dev/null +++ b/ssl/client-certs/index.txt.attr @@ -0,0 +1 @@ +unique_subject = yes diff --git a/ssl/client-certs/index.txt.old b/ssl/client-certs/index.txt.old new file mode 100644 index 00000000..e69de29b diff --git a/ssl/make-certs.sh b/ssl/make-certs.sh new file mode 100755 index 00000000..8f1afd19 --- /dev/null +++ b/ssl/make-certs.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Generate the root (GIVE IT A PASSWORD IF YOU'RE NOT AUTOMATING SIGNING!): +echo 'MAKING CA' +openssl genrsa -out certificate-authority/ca.key 2048 +openssl req -new -x509 -days 7300 -key certificate-authority/ca.key -sha256 -extensions v3_ca -out certificate-authority/ca.crt + +# Generate the domain key: +openssl genrsa -out server-certs/dev.cac.atat.codes.key 2048 + +echo 'MAKING CSR' +# Generate the certificate signing request +openssl req -nodes -sha256 -new -key server-certs/dev.cac.atat.codes.key -out server-certs/dev.cac.atat.codes.csr -reqexts SAN -config <(cat req.cnf <(printf "[SAN]\nsubjectAltName=DNS.1:dev.cac.atat.codes,DNS.2:cac.atat.codes,DNS.3:backend")) + +# Sign the request with your root key +openssl x509 -sha256 -req -in server-certs/dev.cac.atat.codes.csr -CA certificate-authority/ca.crt -CAkey certificate-authority/ca.key -CAcreateserial -out server-certs/dev.cac.atat.codes.crt -days 7300 -extfile <(cat req.cnf <(printf "[SAN]\nsubjectAltName=DNS.1:dev.cac.atat.codes,DNS.2:cac.atat.codes,DNS.3:backend")) -extensions SAN + +# Check your homework: +openssl verify -CAfile certificate-authority/ca.crt server-certs/dev.cac.atat.codes.crt diff --git a/ssl/req.cnf b/ssl/req.cnf new file mode 100644 index 00000000..a3e14495 --- /dev/null +++ b/ssl/req.cnf @@ -0,0 +1,26 @@ +[req] + +distinguished_name = req_distinguished_name +x509_extensions = v3_req +prompt = no + +[req_distinguished_name] + +C = US +ST = VA +L = SomeCity +O = MyCompany +OU = MyDivision +CN = dev.cac.atat.codes + +[v3_req] + +keyUsage = keyEncipherment, dataEncipherment +extendedKeyUsage = serverAuth +subjectAltName = @alt_names + +[alt_names] + +DNS.1 = dev.cac.atat.codes +DNS.2 = cac.atat.codes +DNS.3 = backend diff --git a/ssl/server-certs/ca-chain.pem b/ssl/server-certs/ca-chain.pem new file mode 100644 index 00000000..0d6f3703 --- /dev/null +++ b/ssl/server-certs/ca-chain.pem @@ -0,0 +1,1352 @@ +-----BEGIN CERTIFICATE----- +MIIElTCCA32gAwIBAgIJAN5qDki+VlfPMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYD +VQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZhbmlhMRUwEwYDVQQHEwxQaGlsYWRl +bHBoaWExEDAOBgNVBAoTB0ZhdXhEb0QxCzAJBgNVBAsTAlBXMREwDwYDVQQDEwhG +YXV4IERvRDEeMBwGCSqGSIb3DQEJARYPZmF1eGRvZEBkb2QuY29tMB4XDTE4MDYy +MDIwMzg0N1oXDTE5MDYyMDIwMzg0N1owgY0xCzAJBgNVBAYTAlVTMRUwEwYDVQQI +EwxQZW5uc3lsdmFuaWExFTATBgNVBAcTDFBoaWxhZGVscGhpYTEQMA4GA1UEChMH +RmF1eERvRDELMAkGA1UECxMCUFcxETAPBgNVBAMTCEZhdXggRG9EMR4wHAYJKoZI +hvcNAQkBFg9mYXV4ZG9kQGRvZC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDyQUFcuQ+YKOEJtv4XjKOTpOLp8IdbsaFwU8YgenMdvAc1ONZRL/2o +jaCZx+kB2QSCVH2jaLUQ/2i4uz4rE21Ngpx+EHa1hgDQANle3d5CWrn2Q10/pdPe +rJHYkMSiZ3cNWfFPBfHDtJrLlRUwJkgy+lUSLnOaipmBZMYXbV8/qUh69nWJQNXi +AvmSUw8jwUPfTrpQVzftkOYz+0HVJyvKijTsj1LaPZTR3D8OhbFnvZWIlhIUjJZO +jap/xQ3YEOcNF+gfx8hDQG2SnltWgecPsgiBRXmZK2IqDv39DE2DNiukEclZLhbN +SpTibNZwkVzcTSRV2mSOHKXqTcH0wTvpAgMBAAGjgfUwgfIwHQYDVR0OBBYEFAo/ +6auHcKMK1ItTElg1Kk4MyoB5MIHCBgNVHSMEgbowgbeAFAo/6auHcKMK1ItTElg1 +Kk4MyoB5oYGTpIGQMIGNMQswCQYDVQQGEwJVUzEVMBMGA1UECBMMUGVubnN5bHZh +bmlhMRUwEwYDVQQHEwxQaGlsYWRlbHBoaWExEDAOBgNVBAoTB0ZhdXhEb0QxCzAJ +BgNVBAsTAlBXMREwDwYDVQQDEwhGYXV4IERvRDEeMBwGCSqGSIb3DQEJARYPZmF1 +eGRvZEBkb2QuY29tggkA3moOSL5WV88wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B +AQUFAAOCAQEAp4fVYeSKYJICBQt37NOF6qZ+dv8GBDI+oZy7vC+VcjiRaODkiz9w +IO5dBZxx/ldH5sD24Oc2SH+48S6UjE/D5kDpM/nIddfVfL2f222sE14RsqgrhmbG +qRaEB8NXWiSQyKOKX63v8scioUqb9hFY+gtwb8HDFiOZFx+67L/NaXSh6VA8BbLj +o55EafjTgr+Yad7SrZI5f6Q2iQ+uuHcJsf7fEe3Kts5Uwt5KXBBfMxeaSyQRxNX+ +JBBmy6MaxddPtus3MH+eIgI2Wp2rofH/PtGnSoizBj5IZXBkc18x1DG5pAJL4205 +EKQoicsafE27XBw45dK3cRBLXPWt8JrCBg== +-----END CERTIFICATE----- +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD SW CA-58 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 5 +-----BEGIN CERTIFICATE----- +MIIDHTCCAqOgAwIBAgIBETAKBggqhkjOPQQDAzBbMQswCQYDVQQGEwJVUzEYMBYG +A1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BL +STEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgNTAeFw0xNjEyMTMxNDQwNTJaFw0yMjEy +MTIxNDQwNTJaMFoxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1l +bnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRUwEwYDVQQDEwxET0QgU1cg +Q0EtNTgwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASi6z3lLSwaqQ6FPQrMxlIW2VBf +xYzA7f+z3pBb2AzNVnMVsRMbMe2f3LCLaAK3kVHbf2MFvd00UCQTaJNoBLrsL7pz +SA3jHtBglzOwI5755VNZydC2aK5Ozw+a2yMQrv+jggE6MIIBNjAfBgNVHSMEGDAW +gBSGwBVC+3F23D4tEVshEEQ1ysHcFDAdBgNVHQ4EFgQUJFUaC5AhLNYjqojSnum4 +raKAfdwwDgYDVR0PAQH/BAQDAgEGMD0GA1UdIAQ2MDQwCwYJYIZIAWUCAQsmMAsG +CWCGSAFlAgELKTALBglghkgBZQIBCywwCwYJYIZIAWUCAQs7MBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8v +Y3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0E1LmNybDBKBggrBgEFBQcBAQQ+MDww +OgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9P +VENBNV9JVC5wN2MwCgYIKoZIzj0EAwMDaAAwZQIxAKil1qozXdz7E7kAOhaZ7rOG +81/dVR5o2KGPFavrto3g9eBE1SboimiKKiiveNnhtQIwLNAaeZukpj9sDs2e16vu +s4rRqS3tuansdH1Fy8j9InJojBLaYeJR60j0AchyqvaG +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD SW CA-57 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 5 +-----BEGIN CERTIFICATE----- +MIIDHTCCAqOgAwIBAgIBEDAKBggqhkjOPQQDAzBbMQswCQYDVQQGEwJVUzEYMBYG +A1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BL +STEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgNTAeFw0xNjEyMTMxNDM5NDlaFw0yMjEy +MTIxNDM5NDlaMFoxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1l +bnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRUwEwYDVQQDEwxET0QgU1cg +Q0EtNTcwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARnTnlhX1XAyZxEwrGRe6CpxNu/ +/EDg3NjbHIEknhq5sh7gCEwtpy3+B37ss64mWq88JTWrtjdmmsuWDQgU6Y6x6QUM +8NnU/iEILAdH+d8YC/OCoxxUdz13Hhkdlt1JB/6jggE6MIIBNjAfBgNVHSMEGDAW +gBSGwBVC+3F23D4tEVshEEQ1ysHcFDAdBgNVHQ4EFgQUWhIprDfUjj71jVO1IvA6 +BAnRo+swDgYDVR0PAQH/BAQDAgEGMD0GA1UdIAQ2MDQwCwYJYIZIAWUCAQsmMAsG +CWCGSAFlAgELKTALBglghkgBZQIBCywwCwYJYIZIAWUCAQs7MBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8v +Y3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0E1LmNybDBKBggrBgEFBQcBAQQ+MDww +OgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9P +VENBNV9JVC5wN2MwCgYIKoZIzj0EAwMDaAAwZQIxAJ0s/tXCmJaEmNjh96qg3PQR +JidParsm6DRIOPgL2umoWx9QQP5mCHebRXk/KBOvpwIwUEw7/IxrYi5bF+kZNnw0 +qansI3GZB9080HFde2/owhIWZ5GMDV8mKKhoNVn3kY/D +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 5 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 5 +-----BEGIN CERTIFICATE----- +MIICJDCCAaqgAwIBAgIBDzAKBggqhkjOPQQDAzBbMQswCQYDVQQGEwJVUzEYMBYG +A1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BL +STEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgNTAeFw0xNjA2MTQxNzE3MjdaFw00MTA2 +MTQxNzE3MjdaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1l +bnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0QgUm9v +dCBDQSA1MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENmLeC07Ax9cpRTp/HJnmKiF2 +sQDdjEf/wLG0+s46TlL7p+02LRweHJCNl6orpuLTc3N8XBzQZ/QKKdOQhOtR5fFe +HMDShoTFbdEkSQ7sF4nkaMjeGlwaBtA4GTMpARqBo0IwQDAdBgNVHQ4EFgQUhsAV +Qvtxdtw+LRFbIRBENcrB3BQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wCgYIKoZIzj0EAwMDaAAwZQIwQQbk3t5iNJ3fuKoW2W2iOB85IlfJcIQfkw9X +fgUvpUszzRXqV9XSKx+bjXzOarbMAjEAt4HS4TuTzxFk3AsvF9Jt1dgF5FByYmXc +pDzKYaUGmsn77cQwyXuJ4KW+Y1XmnBHj +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD SW CA-56 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 4 +-----BEGIN CERTIFICATE----- +MIIC4zCCAoigAwIBAgIBSTAMBggqhkjOPQQDAgUAMFsxCzAJBgNVBAYTAlVTMRgw +FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMD +UEtJMRYwFAYDVQQDEw1Eb0QgUm9vdCBDQSA0MB4XDTE2MTEyMjE1NDgyMloXDTIy +MTEyMzE1NDgyMlowWjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1UuUy4gR292ZXJu +bWVudDEMMAoGA1UECwwDRG9EMQwwCgYDVQQLDANQS0kxFTATBgNVBAMMDERPRCBT +VyBDQS01NjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJ8P6wqfbu85tSo6iiVb +QpyTzVfDbEcUuojsnZxa2ZviI59J9fOB6LkSxvoaclcIDG2CQHb/cTFRlYnmny28 +qhajggE6MIIBNjAfBgNVHSMEGDAWgBS9wblrTfQd7DCQv2JzwIQz8nEkhTAdBgNV +HQ4EFgQUvPL0UZ0qy+OdEFZjBXZWyd261FswDgYDVR0PAQH/BAQDAgGGMD0GA1Ud +IAQ2MDQwCwYJYIZIAWUCAQslMAsGCWCGSAFlAgELKDALBglghkgBZQIBCyswCwYJ +YIZIAWUCAQs7MBIGA1UdEwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNV +HR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0E0 +LmNybDBKBggrBgEFBQcBAQQ+MDwwOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlz +YS5taWwvaXNzdWVkdG8vRE9EUk9PVENBNF9JVC5wN2MwDAYIKoZIzj0EAwIFAANH +ADBEAiBjgR3FzwuqcKfmIAyyghC85+C4WZWLlLV/pnA+KF16igIgdT3W8YPHEMGh +WPpqVeBR1xJfFBl4H+a8OxmJ8RTZdUQ= +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD SW CA-55 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 4 +-----BEGIN CERTIFICATE----- +MIIC5TCCAoigAwIBAgIBSDAMBggqhkjOPQQDAgUAMFsxCzAJBgNVBAYTAlVTMRgw +FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMD +UEtJMRYwFAYDVQQDEw1Eb0QgUm9vdCBDQSA0MB4XDTE2MTEyMjE1NDY0NloXDTIy +MTEyMzE1NDY0NlowWjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1UuUy4gR292ZXJu +bWVudDEMMAoGA1UECwwDRG9EMQwwCgYDVQQLDANQS0kxFTATBgNVBAMMDERPRCBT +VyBDQS01NTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDmzh2HFjUhGEaKxXU5E +jVU66fMJbN52tWk4QsBIU8rCcuKdzyoY3DTULRv5WdF4mjPHBTfycuWOmxztrU64 +N+ajggE6MIIBNjAfBgNVHSMEGDAWgBS9wblrTfQd7DCQv2JzwIQz8nEkhTAdBgNV +HQ4EFgQUpW9LHZK1y9132ba9SAa+BkgJNBgwDgYDVR0PAQH/BAQDAgGGMD0GA1Ud +IAQ2MDQwCwYJYIZIAWUCAQslMAsGCWCGSAFlAgELKDALBglghkgBZQIBCyswCwYJ +YIZIAWUCAQs7MBIGA1UdEwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNV +HR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0E0 +LmNybDBKBggrBgEFBQcBAQQ+MDwwOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlz +YS5taWwvaXNzdWVkdG8vRE9EUk9PVENBNF9JVC5wN2MwDAYIKoZIzj0EAwIFAANJ +ADBGAiEA8zQA+T3anaM0b1QsYSEvu8Y95S03GGy8fG2Hoi661FICIQCDCbwQZD1Z +8NhnjbOBDEonqzFEdiXgGiq26ss/1ejDaw== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-48 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 4 +-----BEGIN CERTIFICATE----- +MIIC2jCCAn6gAwIBAgIBCjAMBggqhkjOPQQDAgUAMFsxCzAJBgNVBAYTAlVTMRgw +FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMD +UEtJMRYwFAYDVQQDEw1Eb0QgUm9vdCBDQSA0MB4XDTE2MDQxMjEzMTk0OVoXDTIy +MDQxMzEzMTk0OVowXTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJu +bWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQLEwNQS0kxGDAWBgNVBAMTD0RPRCBJ +RCBTVyBDQS00ODBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHP3gMIrM5XHrtPg +Np7Bm42eqJiheI0fMNe9WDJkFdJbJeTrdxUtYQJfb4nYmLlnGG7Bw3RLHhLhS0vi +MO0inc2jggEtMIIBKTAfBgNVHSMEGDAWgBS9wblrTfQd7DCQv2JzwIQz8nEkhTAd +BgNVHQ4EFgQUtraXanDTuzYAuelFdC8nlSryWQkwDgYDVR0PAQH/BAQDAgGGMDAG +A1UdIAQpMCcwCwYJYIZIAWUCAQsoMAsGCWCGSAFlAgELKzALBglghkgBZQIBCyUw +EgYDVR0TAQH/BAgwBgEB/wIBADAMBgNVHSQEBTADgAEAMDcGA1UdHwQwMC4wLKAq +oCiGJmh0dHA6Ly9jcmwuZGlzYS5taWwvY3JsL0RPRFJPT1RDQTQuY3JsMEoGCCsG +AQUFBwEBBD4wPDA6BggrBgEFBQcwAoYuaHR0cDovL2NybC5kaXNhLm1pbC9pc3N1 +ZWR0by9ET0RST09UQ0E0X0lULnA3YzAMBggqhkjOPQQDAgUAA0gAMEUCIQC+iGG8 +kjbV/VNcKlxuuufzU0hVa3nbY+AH1G/019EVGgIgOBioOJjL2DEOswswow0z0Way +O+Dq52y9IIt1LNiEuQw= +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-47 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 4 +-----BEGIN CERTIFICATE----- +MIIC2zCCAn6gAwIBAgIBCTAMBggqhkjOPQQDAgUAMFsxCzAJBgNVBAYTAlVTMRgw +FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMD +UEtJMRYwFAYDVQQDEw1Eb0QgUm9vdCBDQSA0MB4XDTE2MDQxMjEzMTI0M1oXDTIy +MDQxMzEzMTI0M1owXTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJu +bWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQLEwNQS0kxGDAWBgNVBAMTD0RPRCBJ +RCBTVyBDQS00NzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIXYA5Gtzjuc8KIc +kgMu3+mgBPldfBkOr9i+4whQzY84FDKvzsc78BbuQicWDsbJDXN45N5ACoAkwrIz +MP1NRZyjggEtMIIBKTAfBgNVHSMEGDAWgBS9wblrTfQd7DCQv2JzwIQz8nEkhTAd +BgNVHQ4EFgQUowEMSwGcEB8madmOXGcnxdqsNnowDgYDVR0PAQH/BAQDAgGGMDAG +A1UdIAQpMCcwCwYJYIZIAWUCAQsoMAsGCWCGSAFlAgELKzALBglghkgBZQIBCyUw +EgYDVR0TAQH/BAgwBgEB/wIBADAMBgNVHSQEBTADgAEAMDcGA1UdHwQwMC4wLKAq +oCiGJmh0dHA6Ly9jcmwuZGlzYS5taWwvY3JsL0RPRFJPT1RDQTQuY3JsMEoGCCsG +AQUFBwEBBD4wPDA6BggrBgEFBQcwAoYuaHR0cDovL2NybC5kaXNhLm1pbC9pc3N1 +ZWR0by9ET0RST09UQ0E0X0lULnA3YzAMBggqhkjOPQQDAgUAA0kAMEYCIQCN7jJe +h0KGZ05OTCbxZKgvqR7N3hco4qTXcETpm1mPmAIhAPZWclBf54lOCDQku0UBz8gW +lYdeVXmiuKz7DveFthis +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 4 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 4 +-----BEGIN CERTIFICATE----- +MIIB6zCCAY+gAwIBAgIBATAMBggqhkjOPQQDAgUAMFsxCzAJBgNVBAYTAlVTMRgw +FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMD +UEtJMRYwFAYDVQQDEw1Eb0QgUm9vdCBDQSA0MB4XDTEyMDczMDE5NDgyM1oXDTMy +MDcyNTE5NDgyM1owWzELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJu +bWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQLEwNQS0kxFjAUBgNVBAMTDURvRCBS +b290IENBIDQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR2yNhDyw8H0iwPKtA4 +8YLNQlXn3B1agLcIkUtU1k+yZoU0lo0uPvTgSpF8zM2GnxHgUqFmgsbLkCPsX1/1 +8DxFo0IwQDAdBgNVHQ4EFgQUvcG5a030HewwkL9ic8CEM/JxJIUwDgYDVR0PAQH/ +BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDAYIKoZIzj0EAwIFAANIADBFAiEA6GGK +99yqCaUH0kSeggNaRFNHhCOZz1zT3kpe1rs1NUYCIHYPuMR8FjV/1BLtiD2AEWtk +B0xFZd9Trl8B7fFD0vW3 +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-46 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIErjCCA5agAwIBAgIBZDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNjAzMDgxNDIyMjdaFw0y +MjAzMDkxNDIyMjdaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +SUQgU1cgQ0EtNDYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDB8t7O +izHtqCLUKXdNcAOYlJDNyNoqW22ZB75KiU3GJna5ww499SOnBaEU4OvRSMI3FcKS +lZRvJJIbNpcUbn6X/4cEH6g64lCGSXcm8nl/rU1W0onf7l/fk8tcaVRG0hP9iTbe +7fjlJ7hEWwKEXSk7Xkr/3e09bvKIHVtiCsV6cOlNsK6H7JbEhRw4yPOkqdXtrpQX +mNh9Y6OGya91I1vzYO+zcexr2+MOoHFJyADBVF/+LrMWdRqVI0Fl8r8NXKnGXpC7 +yPns28gz1egmxJ5NsJtQ8p4WHMQnA6J3wPr+7na+5MKzLgCIoMxD2vIJ0FU28ODE +WrAb9clqWqv/Jte/AgMBAAGjggF5MIIBdTAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUW2dpXrVYC5wfCdw1fZvWJ+5iqpwwDgYDVR0P +AQH/BAQDAgGGMFoGA1UdIARTMFEwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMAwGCmCGSAFl +AwIBAycwEgYDVR0TAQH/BAgwBgEB/wIBADAMBgNVHSQEBTADgAEAMDcGA1UdHwQw +MC4wLKAqoCiGJmh0dHA6Ly9jcmwuZGlzYS5taWwvY3JsL0RPRFJPT1RDQTMuY3Js +MGwGCCsGAQUFBwEBBGAwXjA6BggrBgEFBQcwAoYuaHR0cDovL2NybC5kaXNhLm1p +bC9pc3N1ZWR0by9ET0RST09UQ0EzX0lULnA3YzAgBggrBgEFBQcwAYYUaHR0cDov +L29jc3AuZGlzYS5taWwwDQYJKoZIhvcNAQELBQADggEBAHrAmFSy86ZAscEU5KID +UdXtfC3+OV/I1BYnYiZHJKJj8zRuqvdWvsulKtCGKZo1wFv446n/14YRbI3TKno2 +Q/c4J6uz+MOsIGLyPvPmwO5Y6Gaqj5EDD6rgyYSRdHrmBlLE1aUmedc86UOMKAz6 +OwmUFRru8aXF/YSEWQmkeIWX4saImbv8Evb2vqjDPFERjH6BebYDRI7ZpMWg8jJt +LnQFoKOhCOTnHJz0vd/vnh4IC+7+KNgbg+RZ0O3H9dnBeULcLGeHtw2F2jBMrlyW +d0Iyn7vj9cOGkdrkggSpdGqqlXiNkVsYhyPXztL8jOqmyY7ndXubEQCsYxMIIXur +SEQ= +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-45 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIErjCCA5agAwIBAgIBYzANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNjAzMDgxMzI4NTZaFw0y +MjAzMDkxMzI4NTZaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +SUQgU1cgQ0EtNDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVVtcp +RJMdLbl4C4dfjcBCfAqUMLRbXiKiDRnAMXn3c5IrYEND7uJKJTCrQklQ8YC570Za +YXxhSaKiFbcR0MA7oHEF8HWglB53GSmFowqtAiERS/AWbMJoXlh/MBJweeSVUzat +CPO8V3q56Y/5OFglW5YV3tA3Kgv+BvlqjYCzWNeBwfyeglkB8EWi58llAiyjsGPd +QpN71LOyqHK16SCv22E6mIyrxfFgeaWIxIBeXzgVxDzZ2djbsqYyrJlAdUCbGzh/ +O9N0MhEC0mMRcgo7uER0olnWri1oOWtJl2Ok8ZvMqGQbdkxkkmxCthUWyxFoVq7P +xU7IYmBiBn27SyF7AgMBAAGjggF5MIIBdTAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUy/0Vpppg8S5OW5UcjD8djcKjIhswDgYDVR0P +AQH/BAQDAgGGMFoGA1UdIARTMFEwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMAwGCmCGSAFl +AwIBAycwEgYDVR0TAQH/BAgwBgEB/wIBADAMBgNVHSQEBTADgAEAMDcGA1UdHwQw +MC4wLKAqoCiGJmh0dHA6Ly9jcmwuZGlzYS5taWwvY3JsL0RPRFJPT1RDQTMuY3Js +MGwGCCsGAQUFBwEBBGAwXjA6BggrBgEFBQcwAoYuaHR0cDovL2NybC5kaXNhLm1p +bC9pc3N1ZWR0by9ET0RST09UQ0EzX0lULnA3YzAgBggrBgEFBQcwAYYUaHR0cDov +L29jc3AuZGlzYS5taWwwDQYJKoZIhvcNAQELBQADggEBADPubZ/kZNDB/hkuGuuK +OmiGZJC2C1dBGkuM0SXewWzGHEPKapa4rNDrgDSTQMOLeMUCmr4XbHbMo1mqIDBc +SioVFiq+CooCskj3D+gj1Y+dbfi+IW8/IlbHVDxlApDlJ11v3nvNJNHp7gA0hFVD +Da2Upj9wVsYr0ReXvHRz0Zb6a1/7R6to41c8wwg3hWCGCXsPvnILaQK5JmxNVX1i +HT95UKDxnysb+vw+GxxJgaIH87HkgxZtOc7WUnP+GFALfKQyLsR8J3vkIkI2DJfP +FjtBblgXWn9lCI5lYgeH3VbKjVvowcUWuw2F8PJaaNHpVpWwv+XfzLmUCdLGjZrB +zBQ= +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-44 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEnTCCA4WgAwIBAgIBGzANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjE4MTRaFw0y +MTExMDkxNjE4MTRaMFoxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRUwEwYDVQQDEwxET0Qg +SUQgQ0EtNDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDG3+Tty+pD +oTJGbJvbL/uQUD5vXkR1G6vSxNSbFskImmrpLV2hr8uCGAFDL+Kb3dPaYLTEeaK9 +34LqDC02+Cw4mLamoXKtfBGlFT1T3AHzpS4wJAhfrSGFGRBdY76jpTn1eiaWs+nb +CLiJjpxQOQhp7caytsZnGvLNOFUc+QZJFsyAf06cpWEmo/iAx7KXLMPV6sbGTLqm +kyqNxYPvqd1Ryyq2vi5Pqyw0swg2+wvkMhGIZ39ryJhgaU5vcAhd39z53tNU1ttp +xP506Z4uDG9TmBciUFfs4uZbz9aOzT9YYs6enlh172PU48WfCFIQSOXjRcB9/XkD +btghMxTcmzgRAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2Behaq +8tzOZu5FwDAdBgNVHQ4EFgQUMPnNVHOQG4Lyco6N7lZGokQpv/owDgYDVR0PAQH/ +BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzALBglg +hkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8v +Y3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRgMF4w +OgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9P +VENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0G +CSqGSIb3DQEBCwUAA4IBAQCnFaVDUuNpbT4YazfYL4qKc/e0Zqd1wM10uqo+ayjz +zP5HXLL2frAudguRVxFDC1WzjB16tc1GODUWY4OOxPCyUNKUJTU3G8qcXMabjEvC +y9wLu/5FTvE0iumpvdpSGJb2v/pBc+Tofe17SgCTpOW+METZM5fiV6e8VrYaZalg +YXrHg+DvdBpGSteccLFLORhZoq0ZpHh7QoHNVOi9sxLhEuhRTSGebRhTkYN99PzC +BdD6ljQ0uShqB3r8uX1pVpBskdovm2JWSX40/QahFVDMwJPImlJ7lXRNvRrkqLHH +PaTJ4R5spBJULmUEbqVfFXG5p/I9vNVF7YZCE5nzegTf +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-43 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEnTCCA4WgAwIBAgIBGjANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjE2MDFaFw0y +MTExMDkxNjE2MDFaMFoxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRUwEwYDVQQDEwxET0Qg +SUQgQ0EtNDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCib5WKgEkw +yV+HYIReCPRrFLoBoue/va3ODbll8dZITF5Dkj/Qpn/aE3cCVXkd1Oy38k+7MFGo +I93xCKkxq+gdkeLGXEZ8tuwpuqeVHW7rjgd+2DgDuNWsXkN8UqfJvaMccLSjLfTI +MS420x3sMtE5aOC+Zib6Ei7YlT5GUatw33BKSTZIsXqWa9tag6daktv1JonQOs9W +z+zCwZ806AmJhygNzv5scv0+Wtbns91UzwyTBSpYi8Go03YXU1znT/hciQC6uXRY +xUWbBRkuJyc4AsGb2mwfcfG7Tv3LoO1sv1VUV0FswWGP9dFRX3DqjIzs5ylk58oo +CXTCrwOYIXGPAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2Behaq +8tzOZu5FwDAdBgNVHQ4EFgQUN6mSY1xcxJ27IUhTKKrUZFBmmkUwDgYDVR0PAQH/ +BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzALBglg +hkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8v +Y3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRgMF4w +OgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9P +VENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0G +CSqGSIb3DQEBCwUAA4IBAQBqUrzdeqnC2ohoGUExkxayPe+h3TKunmYUBgFHOLtT +w89DiGAypywUHgjSOqb1DQD7Z2JohlU2rRRn0ajIAii5DtPgGN4mB9Z5HsmdfZ8L ++CMr/Jw7oYeaRLnyWoRW6cvGiM3opBewNo1192dqv7JYHaAGIVKSdLcESJNwp347 +nDD5MauXa8/2a20lsOOrcU8PgpBHhyRPDQoBaxjjSFtH+aA7KwvFaqsUpvgiTqNp +5j41K0ayV0rdd/K3zRKcA2weMONqDXagcvDSCMOu3S6jS/M7oc3Sv4kKk8Vjhcom +hCvw6EHyLSiUMqNzlO71q5q3qMj9QOD6T4PK6/UxRD7D +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-42 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEnTCCA4WgAwIBAgIBGTANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjE1MDJaFw0y +MTExMDkxNjE1MDJaMFoxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRUwEwYDVQQDEwxET0Qg +SUQgQ0EtNDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt4/+9beDb +3g9kGg2MlznUY93COtiDLetMCks4aQ5/MYaSti6eoDw5L7EHlkNfnrO5XXKbQHZ7 +HqipwyE6uZ36WPEvU6ufin57Fr++aIYNk3xLAH4me6jT8qyrzn9FUBXh2UsnqCMo +5jHl+6FJbsTq2/sSpIZl8SMUS4w6wNi/gRSrhdVfmJibhQgEj6QbvUr8aASzlyS9 ++zvMRTZq7JBDEPlbdsfE3mbGWvO0+PD8HMsNrj5rKL7wdoAzQDB/YisF/9ffJw8L +cFPsUisUdZsFTk9L7qMCcgSfCtGfw5AEw4lcmIAiHRX0Apd/iJM4kADuHUFPYzM2 +EN4ngjDxK6jVAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2Behaq +8tzOZu5FwDAdBgNVHQ4EFgQUMqAAylmLxM58e9veGSoQioZB0eMwDgYDVR0PAQH/ +BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzALBglg +hkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8v +Y3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRgMF4w +OgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9P +VENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0G +CSqGSIb3DQEBCwUAA4IBAQA5hIjoPl6je1176wDm7i4FNGehuKkrM6KOqEZLyze2 +bkSRZXV8wIve6CkMxL89PLEa9BPXF/PpF5Wn2to4YZgZmx0j+3M9kIuIzDxKHAHB +tfLoOXHiT/g9U9Scl09RiWVfhul13R7+Q6CQdKO1yu69bNtvL1Uxsz2LaGP3pFaS +QklM+Ns56N3a2YJ3qNyjGnMoksBDFSkitYJJrWteHSv1iBv9FVge/d3SE9+Pq/WD +Q22yK/0ph3gTEw61e9EYZ/TAeNb01Ju56bNo5lVHAz2UawrwGhRklJQhf/i9JRda +gykYg4Zkczl+ZXN+0bfJDZ+kpis0wlcPrVzNKNpAVnzf +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-41 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEnTCCA4WgAwIBAgIBGDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjEzNTZaFw0y +MTExMDkxNjEzNTZaMFoxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRUwEwYDVQQDEwxET0Qg +SUQgQ0EtNDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3yXSI2Ca+ +LJHgzmhn2NH9Xk02+QoEPtO4K3oHa+XKeP2Mdk4ooFy3SLvizf84zDWzqVPoofEd +pF1NpDT89rm5JOjaI5PBm9ct4rV0ZqH34DlARMVjthW6ySUp2YDDK5dGkZTACqkn +E2AaL777RyPLRESDp1p/J2yInUMvCc3wsJmqteSW5dUDpl7+S9SV2D+urf7zB5oB +06D9i4YknSh3nnthtqHSCvNF0QtpynTydycBrZZ2Cv4lF/iVPpi89WDTAjwWc3u7 +HVxHqCi9Z6zB7eIIXtIRcKBJrqL7oExvAGu0C/1D6/dQfOqHa4cPEgllXfy38Zxf +nUrFCih4TjD1AgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2Behaq +8tzOZu5FwDAdBgNVHQ4EFgQUW5HGRDbyKPL4z7LCyMpjSWGbIAowDgYDVR0PAQH/ +BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzALBglg +hkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8v +Y3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRgMF4w +OgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9P +VENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0G +CSqGSIb3DQEBCwUAA4IBAQCh4rRiX98I1sgwJ/wFaLDtM3GlKTulDu7VGpGllllh +bUpZiaHQ8pMV2goFboAOPXxMnl2N2UM/U4/9S2uW4mosQo2gbcNT7rbi/QhlEk4Z +u6tZek3SvhFIq+fn/XhMqiMwIOUNqroh5BnvPGLQcMqfnLebTJmkcG4I6OmXP6en +jh/JcdNnxMhZ1ZUju61+Sw8g14fKV6kAUdrGhQPZAceZyLvUajDRXLdxFX7LWip0 +IIFPD4eM2pLx94MPpbwFo4/l+rO8LK5BLxG4YV7hIiyauwtcREoNwjRyE0TJ8qTf +mzXUzM7YyjBQytyeKHaEyDbULAe0vfUb9p1joxoGSOue +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-44 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEoDCCA4igAwIBAgIBFzANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjEyMTZaFw0y +MTExMDkxNjEyMTZaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +RU1BSUwgQ0EtNDQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5wjjc +RPtz4s4DzWJURVpAl0MhxzRT1SHv3Sju/LkVaagrEfNxEZbnkTHKciFhScbCIco4 +458+LtRXmwMZiXSPSVquEuhYjpmQggqVUs8eozfV4uMnI88FBEGUhwA8zfgwRMLF +RQnJ4SCB3oGbZHh4sV1MutprCDwd6qrG0k8b8/GF9h1vyPZbNNBHODlfdDraBD5/ +bdX5lQ4L6J7uT5vYtTQQIRM+fk1Nlmxr2okKH4wcwK5FQ9I/kYAs7QoF9My8nAOO +sAAYPBxq+V5UWwRqqdSSxX72YEHAyitxmwng3VMHu5pNCnmEsYSVH7C7FfQaXk/e +Q4+o36slG0x/jys7AgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUoItn0eFgZHWnOazJuDWNmJJ0c6UwDgYDVR0P +AQH/BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRw +Oi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRg +MF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9E +Uk9PVENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWls +MA0GCSqGSIb3DQEBCwUAA4IBAQCSY9dTLozPHVTcrSBDSPRiAts6kmKFip1T2qP+ +zDqETUs7FpS/EkLka8n0qjmYMtNWD9zsWKi8FbZeZ1se5tSFxL9waupfibMFsJT4 +Mnvmk3ihhUfTZYpERBmgeX7cd80+WO9SB1P+dCLw/7MjTdN8j0aOcjh+I6KLWLjA +LfVNhpZ7/8LgsOl3sHgZ7537YsA6Ti+yezGD0jM7nKpfyg78nbK2imWutiuEyHui +OdwcJOQpsKuoyNa5yzyuXK5ygG/PMEzJr6rfJykd6UMpADgaCZmSWueJqzMxfrI2 +ZoXlZzmX0xG2CuhOEhcqwLLvKgqu+dUKwzE4VxQYgtRtzzJf +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-43 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEoDCCA4igAwIBAgIBFjANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjExMDJaFw0y +MTExMDkxNjExMDJaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +RU1BSUwgQ0EtNDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCr3inR +YhAew1kjGebIpt5eR5BSz/xqDhz6KvPNiri3gbRar7lAu7XVGAn+LYB+NyuJt3Wu +6tSmXvvqxLPKXr47tFAkjpX2My1IGM+Y59iMsuvK+T1xeFvbZFtnC8EgntEwR0Uo +UWtUZAdb5IdKGquolt89RTt6W1mgMhbuYEewydSknxxUI+yNvMQ6NGeaRzu9IRIm +AmtSHUpkE5vxto8lmxRtF09LcmLSiElx7InsL3olAQSjzw2AWbHEMr4WDVTugJXn +VLfmC8/fuTENvmLRDGnTA+li0fjORzMqmGIok5eoU3X24Qv3Ii7/XvGFyNGAKPy4 +oKAXEGn5eZtar4kvAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQU9x/xRjhVv7xxi7IGO44rGLJeu7QwDgYDVR0P +AQH/BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRw +Oi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRg +MF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9E +Uk9PVENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWls +MA0GCSqGSIb3DQEBCwUAA4IBAQBb0OxJQPngXOTSzqqxRWBYjiK+4vEf/nwj7cj0 +OT07FIrRsRpyZwpENffCtMU5yv2GHqlS8JKiqw9oGNMtqoW4BtXEE0Oo7W0dnQGk +wLv55eRN1FDI0JgpTu4zixq7NMpYx7XVADi6+3E11efmOesF20po7+Gg2MGsJTNR +EMXh7yHcDqs6nMkPtcl1u4qivfohdRcKsIvwC1Z4cV+bjZ9A5KOBZeWsa86FzNBl +jKTdLxebUz091aA6tjUZ/k576OPKiR1k8awlDsz5j/S9xK1Ht5KV2x8Edvgreiw4 +Dt8Disz/fX0T330P2n6GbPOcgL/wiktRjCq2BnnlmDLFwxJe +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-42 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEoDCCA4igAwIBAgIBFTANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjA5NDJaFw0y +MTExMDkxNjA5NDJaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +RU1BSUwgQ0EtNDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCmnSX1 +j25X0lrlxl7FTi65DxzSaXlUQwPPILHxQh4pWMbA7Rff4r+duETma3mrPmaej45H +KYPF+1jFiV+jLiPFXzQKcsrrImratXcABFus0lA8xBtvhjZTE/vmGSXZpBPFAkyb +jof3OJBzzWwo+kPrK/je0Kbrlq4jekNcpXDeR4Qp2FXtwMgeS9RnMGUWbO7sv/iJ +ceUkXD9WG6IY2GW3EMsx5MJtxe6M7ACsMb0J3eN+2BAxAZZGjMRjPa2C+2kc922j +Bsr4mfQ9hEbWEu5wWLwiJLBH+9NaTBxlqcGS8yyX0xQktvLHlrmnIUpQksH3x/6F +UnzXQ1CKhaENi4lvAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUbwWkXaLEr5VbQZHfC3gLFu8cCW4wDgYDVR0P +AQH/BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRw +Oi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRg +MF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9E +Uk9PVENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWls +MA0GCSqGSIb3DQEBCwUAA4IBAQB+0vQGArx8bB3kLkQtlSq/JQdzYG9ZxTu1W+nv +eaBUzXyhUyBP1OEA0ZvyiAt7km95y3/H65mZqtBRQuz+jYf0Hxxd0fFw2cXrU8oN +pf9of8SIit3g7H/lPvCzQrixjBPJyIZiuF/1tGqS7OmQP/4jU3+R8uvVhUi3AX2D +XAm4VTcBpCsG3ozOCpJykAQZJxaOgqSJHFLNdPByr1fMvpsFOkSWwlGzmWObh4Xw +ud0+naP4pbqKYjue/MeAGqgmxMJTn4hFXS5bHMViscJpnZtJz1J6XsA8aSiZO/ul +iO/vQx3CzdEWCMB1ZCGP0xdzfDipKEMDPRpA3ucPj3dgb3Mr +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-41 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEoDCCA4igAwIBAgIBFDANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTExMDkxNjA1MjdaFw0y +MTExMDkxNjA1MjdaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +RU1BSUwgQ0EtNDEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUuycR +DCMw4iPGIbeq1Yuw/9S+tkQnTdtDE1RSp/AhVU+sIILIH0Ay5GiJYuZ1L4NdUGnJ +rsAeRJIFUZae/eMfzARtUtnHyPteXJB1DYh8eK5b5E7RFUz5lae4AdhuUtPSRDm0 +YdH8nXJ8Fgm0w+pMCltZJLIGhfgphXbcZleyFJrRk/k30PIfNdZSoxI0dn8tJRui +8H50cXpDbCd5Ksi+jEsdYR3Mcza6VTZRmvepwAiF9fpEqlyVqltq2OWLg8ky628V +ODeDZ188HSx8rgpZfOxHQJpMnIyOKHH35WeXEMGC7spvrRP+d/BZsIRGmVx25FTi +jbCFfTQeD91cb6ifAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUOSmoCGTij4OqgWFHEZEz+Fo3puQwDgYDVR0P +AQH/BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRw +Oi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRg +MF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9E +Uk9PVENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWls +MA0GCSqGSIb3DQEBCwUAA4IBAQAhEvHTWyebz05Ox9hW+neUMYI1686yzQA3er3T +lmapTCnxNyNeGP0dcLuFqHZu7wiw6n362ygHDB4e2GQm/IFHsdPXBEQiDBtBOe24 +EOxXMEp4Ku0znOFgZEV/kng/ST4rsoyb4MVCzhCR/5lfzk0zWD5oUgnJ5YwWIITN +zCO10fxQYiCBFDGPcMGJ/biBdcXFtzvPmrzIHDgitll91kI4Rtq5Z8K7988yqqsM +Dm/Ec1t7aL+A+PH9CSLMLNYfllANDvpS2qGV9vh4RGjO4d8P8WAejNczrcuQ4GEA +1aInA29sNdhLFOKAt3BDKvSjxJM/b3J3jkg6CDzmccXolN/y +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-38 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEoDCCA4igAwIBAgIBEzANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTA5MjMxNTI0NTFaFw0y +MTA5MjMxNTI0NTFaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +SUQgU1cgQ0EtMzgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDMtw2M +Q24eg6nE7h/ZXMiN0GTHnybtceAlYm5NmOWZNzr1/s22At1aN3NSilt5T2MAq7IJ +OOPVqtQ4e8YjvwnZMl/vhk6Z4rwAePshr9HvlO8CXl257RP3uN8HgRBRyiBzJh08 +Q8W+Hrb77XMn0CzdQ7h+0+hJjdwRjSAgHfHBagAFIilYBUHtresJNB7zk/jedaIu +v6xoTkJttS+USSWJ91Rqn1hvAZfd4XbweSqCPNFXXWvudII7DZ9G3ViymCXqXJDZ +KXW+iEOFewY9K1BMnI+NOV/qOv335oitPYeRqnIOiQmV0J2ArCYoWfQputQuHD6Y +y3dzTEj6dFH9CbuXAgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUjsW5zPzOjlO0Ks7oESrPmylsZ8owDgYDVR0P +AQH/BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRw +Oi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRg +MF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9E +Uk9PVENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWls +MA0GCSqGSIb3DQEBCwUAA4IBAQChLaZGtZEevrRh4hyMrywIePJ1h8t8K766TTUB +8AY2y5/BolEoHxKTOis7BRolriRFsa4PVFUSIXUsGQxrA2h8pa0v2irrEE2ixZGN +h5rSXXhC+UtALDF8PlWUvD/M1WLOIW277YHQ4JNjMl5OEhsrVoxJZ3I32bTG8EZp +EDmBbVPsBINRf1kjBd69xb7kk67DfUEs4fUjTHRDOflV388bX2877//UaADPfjGK +6g9AxY++pf/4can/DhxhJ40+oKiDN29apuwmeNrfAi+CqL9uFu6JSxSUGOy4ZDLA +vmAQHGI6r+mRBcu8U/9xuaYpkO8jAoDNn7yS4H0STEoDorrR +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-37 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEoDCCA4igAwIBAgIBEjANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xNTA5MjMxNTIzMDVaFw0y +MTA5MjMxNTIzMDVaMF0xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRgwFgYDVQQDEw9ET0Qg +SUQgU1cgQ0EtMzcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsrnKi +qfWUYvBZ5poN5GMO6qotl7XJ4GGfg/lr8ipbPcgYScw8HLXrxakW0wA+uEk3Yka/ +/bfUgtiLCqr2/SMYVISjXisglAHUiK1pnXl6ANJ3FGX4eio9XdbvifXjcMu462T3 +XoZAcbbwkk7j5G2P4uJn88h2GmprYJzePNLC38yMgi4FMRsPchVYpX3Fxk2wXEOg +hyeSYvueXWOzEtEDCEyrumQxHfW3Oru0b6JrTZMpztOlaTd9ngKLrIcKaXEyGtrj +lCokBmTALc6xnyKmUNf4R9Imo+lVbwSIycGnePOTrJccRTUbZsfXsFeD0lIWGnHY +rws1w9xarvIN7Gm9AgMBAAGjggFrMIIBZzAfBgNVHSMEGDAWgBRsipSid7GAch2B +ehaq8tzOZu5FwDAdBgNVHQ4EFgQUFiR+9y3B75I/vkTnVF7p/he686EwDgYDVR0P +AQH/BAQDAgGGMEwGA1UdIARFMEMwCwYJYIZIAWUCAQskMAsGCWCGSAFlAgELJzAL +BglghkgBZQIBCyowDAYKYIZIAWUDAgEDDTAMBgpghkgBZQMCAQMRMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADA3BgNVHR8EMDAuMCygKqAohiZodHRw +Oi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09UQ0EzLmNybDBsBggrBgEFBQcBAQRg +MF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9E +Uk9PVENBM19JVC5wN2MwIAYIKwYBBQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWls +MA0GCSqGSIb3DQEBCwUAA4IBAQBZDRYy0oP+yD3OiDqM3liOggDDqJidDSkqmPMB +pxTL9iyXCAqS5OUhzKQ2/N8gRYzO1o7JNIqez7kuwj1HJ0LH94jbjyMnvrWV34mh +m1OzbG1y/88FvheQXLgld+tjojxYVhErbFGHnxMPw1X0VpbRTWrAcetlfMNKdwPU +AH1GDfFmczuSfqwqZcapgJal9BWMIJoCXH1sUOHXmg/6anXx1d30OH9iTYV0to76 +oHTg6PEw7nwxNDgGcVgLDVyDAyTpfQCfhV4fSLI9cDTs4nA0SUgUga01d2h1Sp4r +0PtksjJINJlYvLggvRWucI/MokLw5F6m+w6BN+t+kEggLn6T +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMzAeFw0xMjAzMjAxODQ2NDFaFw0y +OTEyMzAxODQ2NDFaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0Qg +Um9vdCBDQSAzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqewUcoro +S3Cj2hADhKb7pzYNKjpSFr8wFVKGBUcgz6qmzXXEZG7v8WAjywpmQK60yGgqAFFo +STfpWTJNlbxDJ+lAjToQzhS8Qxih+d7M54V2c14YGiNbvT8f8u2NGcwD0UCkj6cg +AkwnWnk29qM3IY4AWgYWytNVlm8xKbtyDsviSFHy1DekNdZv7hezsQarCxmG6CNt +MRsoeGXF3mJSvMF96+6gXVQE+7LLK7IjVJGCTPC/unRAOwwERYBnXMXrolfDGn8K +Lb1/udzBmbDIB+QMhjaUOiUv8n3mlzwblLSXWQbJOuQL2erp/DtzNG/955jk86HC +kF8c9T8u1xnTfwIDAQABo0IwQDAdBgNVHQ4EFgQUbIqUonexgHIdgXoWqvLczmbu +RcAwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL +BQADggEBAJ9xpMC2ltKAQ6BI6R92BPnFPK1mGFhjm8O26GiKhVpCZhK00uaLiH+H +9Jj1qMYJyR/wLB/sgrj0pUc4wTMr30x+mr4LC7HLD3xQKBDPio2i6bqshtfUsZNf +Io+WBbRODHWRfdPy55TClBR2T48MqxCHWDKFB3WGEgte6lO0CshMhJIf6+hBhjy6 +9E5BStFsWEdBw4Za8u7p8pgnguouNtb4Bl6C8aBSk0QJutKpGVpYo6hdIG1PZPgw +hxuQE0iBzcqQxw3B1Jg/jvIOV2gzEo6ZCbHw5PYQ9DbySb3qozjIVkEjg5rfoRs1 +fOs/QbP1b0s6Xq5vk3aY0vGZnUXEjnI= +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD SW CA-54 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEjzCCA3egAwIBAgICASwwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM1MTI4WhcN +MjIxMTIzMTM1MTI4WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEVMBMGA1UEAwwMRE9E +IFNXIENBLTU0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq0wnaj/j +ZzXRnZnNDN5rMZW7OmPPcrG+8IQW6oHretQqvj/HCnAyX3sl5TvT6bLCG4UfLBAx +4VRCvpsVW9fME/43E+N8pyUDjlhYe8BHO9e0RfbVjMgDh6tLagvjN3MfThg8E94C +6TRisdifkP6WonplO1sbv8YD49GjmBWLs8KtU3xzw/StQrwNfymY8aW4lXJQa/Ca ++FXzz/tRh7Mclrlz6QCzgdHAliWK4s5tsXDxeZls2/tvTaZQCVCiyccDdc//lYzL +UIwg3lnPcoV6CPhhw+QW4q42Y4oSu48Z9g/fAvqhrK1U0S9mHl1vWLDTHI3hkwmd +T/O2WgKh8nvx8wIDAQABo4IBXDCCAVgwHwYDVR0jBBgwFoAUbIqUonexgHIdgXoW +qvLczmbuRcAwHQYDVR0OBBYEFLC3KL8sBImKdCavqhOMAhBVgXmxMA4GA1UdDwEB +/wQEAwIBhjA9BgNVHSAENjA0MAsGCWCGSAFlAgELJDALBglghkgBZQIBCycwCwYJ +YIZIAWUCAQsqMAsGCWCGSAFlAgELOzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1Ud +JAQFMAOAAQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9j +cmwvRE9EUk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5o +dHRwOi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAG +CCsGAQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOC +AQEAZF047yS8bq8lkMpoxFrJjmbdD1TNpjnWRmImQ32uPwNkrDbspNJ4GdqAh3N6 +ueIMcPUSmrIEs9GRZGJzOeTQ6tcQKCyWy+npsI1DQ/k5Xz0H375Bw17gnq2Bpjdy +s8zeg8I+2lDOjSNr7RgVWWB+2sVWXdvILx4Wkh6vX57uEud046HBmc4NeDiHAer8 +NIac5A7e379NRyuusNGXkAm3g7GsE/Y7MrFsKKsMlHb+gFXVgD0DBhtF22YqmA/R +QvTz7Ij1AD++Gv5I4IIzJFMryN6ED6XduWcTtk9Cnf0uY0z+VY8RFw9nOkECFc2b +BA8L2LlruBOzMWbFy4kH7G/hrA== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD SW CA-53 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEjzCCA3egAwIBAgICASswDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM1MDM1WhcN +MjIxMTIzMTM1MDM1WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEVMBMGA1UEAwwMRE9E +IFNXIENBLTUzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwTewS9iv +ChYtMvNBYEOjVcVqr+3VOAEgyjt7ieJUVPrFDgtL9Sz+eXX+uBXkJwYjS0gtex6L +RuNtdcLkukoJu34ZxnfUwc8rgTwNV8VtIyI2GJq/u/FjGwK8fHkzslOzwF8KoA6N +NTYvKy9XohBDrrYGpRq/RuDttVfiJ4Yvcii5J6+uZTvT9035EksqjV7A+sJkFVqI +3MZ83kN9O0ZJf4dEj4h4DKqQYHTRrpy/BL4pTGxmSpnQHne63ToqsoZntTYCYhB5 +6izOakbsUTYVauwYqlNVf0j20IwcZibztp7wqV2NgGzA81LndhYLQh+8KsDabTSV +sZMvLHfEAeLdhwIDAQABo4IBXDCCAVgwHwYDVR0jBBgwFoAUbIqUonexgHIdgXoW +qvLczmbuRcAwHQYDVR0OBBYEFFHEizOZlMB+uzYd4+I6Bb0ydJ1TMA4GA1UdDwEB +/wQEAwIBhjA9BgNVHSAENjA0MAsGCWCGSAFlAgELJDALBglghkgBZQIBCycwCwYJ +YIZIAWUCAQsqMAsGCWCGSAFlAgELOzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1Ud +JAQFMAOAAQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9j +cmwvRE9EUk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5o +dHRwOi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAG +CCsGAQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOC +AQEACZtxX9lr6sye0RUSOLYzLCU4jVDNSQgz3qq8Kk7dJ97GdsuBzACcCIwFDpNd +tjMtD+mwNjgfeRY5ovyMEH3ZzVhIqGpQo4WLeE+bjy3fNcU3rsb2SHNaEpRddWQ3 +jnOc3jlyg/sHaR6Jg4JfQ1G9za46AReVa1nJLHjt/BO5m/3D4iJmpJvq2Qp6N4eF +a2VL6s8uAZKnLCocjZU2B3wYZMyaSgppaE4TOe/Hc5HJw245/cFLUL8I02iYfv9E +KQDuTGqNzGrBuKp9LMpRrBWb0boFrZaONcVXjtCqi05fo1Fd/JhuvfraTpgxmVXi +1OvgVGwq5lsxW2pbjSpBFebaRw== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-52 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgICASowDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0OTU3WhcN +MjIxMTIzMTM0OTU3WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEVMBMGA1UEAwwMRE9E +IElEIENBLTUyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAltzcMp2O +02t+fwd7rTlugoKqYF8eo/3M+JVdppPAHTiJVaVt0JSeM4xyZsKNoPBoFW/yshnx +lRv/LyNx0VBbn+4mJ7Ea1U4FBPxCSZ68VYqKdV64UMhndawVBJM3Oy8Y3ZxPldTD +f9ApCg4dZXSEiSnShO8YuphrNbYAd6YrdUn1IhDAhw90VTU3GMLru4vx60vFHscW +eZHpHfET8AsClbAyqu65bsa1+o0XvGLQy2GTMzEVaR1NhYVWKRSwgqW57gbE8pV+ +63WYNwi8XIr/2TaJ5GvgBVCbgJWAwsSfFTz21ZqOou0d5xYu79iIIue5DEoRW1bm +qserHNG7gsMvHwIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHIdgXoW +qvLczmbuRcAwHQYDVR0OBBYEFJroUayRVNeUmgRI+iJ5/8bV7oYrMA4GA1UdDwEB +/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycwCwYJ +YIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFlAwIB +AxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQFMAOA +AQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwvRE9E +Uk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRwOi8v +Y3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsGAQUF +BzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEAkxvd +sbOh2zGZCsj3nu9fHEMClJVtK4kJzPJZPi44gdSn+U8X5lbtT0kxsRrqCAZntlgQ +mp+DxnQClr35fjao3wF79nQaIOP2789a9VWZgyJfPrV2KLsxAH4/oOd2ZYdUtHfC +lbfZwbpxFulBqPWxysKQOx3XC/3LszCR0YFqbV/c5hBRB1A4sWBlF8KRGQyKdAyc +K7PrLcSMnLq04ugd5MfYWuJjJx/USNNWlil/LzqyCFzxPp4nGBB8y8s2LcZyvofh +HIBN9qxl3+EXcJyeyqyNiVZcgJi+DLSmBCckb2J6lN9tbGWV02WK+8OiAiZ31CfJ +/sezZ58EZayGYS031Q== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-51 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgICASkwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0OTI3WhcN +MjIxMTIzMTM0OTI3WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEVMBMGA1UEAwwMRE9E +IElEIENBLTUxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjjtDs/iL +TIf25t9SGGMP49gCFIYXcEtvTtc/vh+Cghf7qVwiNvUYCaGMq5q7F/pgL5xsw6Bn +iCMau2bZtLfl5xnMk2VMl2GRwUayHQ/0lyteeKid6fa8sfnlyNLh8lvPuHqQFJZX +5vpfAC24NDQCrr8YIkkNRyxJihCpj8HHYuzTplDRIpMljahhAWCsQkUqlq/5Lite +XHYA/+EnT2hspkitSU+FUIWo0FKK95oo+i2uXX8x3cXWEUCXoR23Slk5NrGTwAsf +TUd16xWA1acvksunx8eK3uOVCV02Q0sldVN19NaGm8lpoBfbtiNz3lo/j1VT558q +35LmOYWI6KzSTwIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHIdgXoW +qvLczmbuRcAwHQYDVR0OBBYEFJ2kwVzT+WZxSaiEIwO24a8pdy2uMA4GA1UdDwEB +/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycwCwYJ +YIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFlAwIB +AxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQFMAOA +AQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwvRE9E +Uk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRwOi8v +Y3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsGAQUF +BzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEAigQ4 +aOduTUCpDvC0ue0B0GV49B0aek8HXWKc10bPb1iUCQL2DT4aIf0u+yQqrzVpTw/x +5mVPRn2Zi2iEV5A8PsN4dReF3lblQSrSVvKFw7cq66Z8ab2ijXjpAMTJCUIOir8w +KoOV03cnVcaW0VDTH+gOslXnm95kPqdfbxJMh06Q00XfvWfRjfnB9D8ZDXbytM5X +mkZRyuUvWY+DKyJUy1HAuardaFpgA5WowjeQm9sAvx72LzaS7zmv+hxOliGXYOn7 +gbJATcT+zt1Ffwa9M19FjoQDSzWihW8P5cFRt6xVEwZHeD8VG++jcQfAujwX0v7U +hFKu8gxm3wlNXOalzA== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-50 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgICASgwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0ODQ3WhcN +MjIxMTIzMTM0ODQ3WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEVMBMGA1UEAwwMRE9E +IElEIENBLTUwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy1ncM1bN +JJHiu1Bh5jQ8r+Y1L2pvw+6YDLGE71z5gquBqisOC6XLKffKdBSF2U55vvp0m5J8 +WdF5DSfyfdAJ7S1HlzFYVW+0KjGLELKV5tWZh/aXu8V85ZaaYkvJeeEU5cIYWLKK +RAr1iygwnslhy1Kb7xhYV7gLYc29Wm1EgZiJ2Xm9M11FIauo40EXmQFniz4FLE/S +4JB1lbYiP1jGa4zJrdnec1k65tZk/K4hdi2diS+9mEUz3PWrzNqjrHKxFocnh9qS +NGqJfyfXxXgKTrZw2UG83IxHKvIpMPodX4SYUwRm5HRbrG6c1Fx12NC2go16w3dD +ilH+aUduTNpmFQIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHIdgXoW +qvLczmbuRcAwHQYDVR0OBBYEFDYuUt50qp7sux+T0b62ULXGaQv5MA4GA1UdDwEB +/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycwCwYJ +YIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFlAwIB +AxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQFMAOA +AQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwvRE9E +Uk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRwOi8v +Y3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsGAQUF +BzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEAbAli +o7+gWX5YytmPMD9ic+aX2s0NaSdSauFYmb6khtN0CCocIqTI/TyfRJTjhI6wRNoa +ckcjVa5H3EOp4vOrtLN4TxbhNqdE+IHafWE4/btDstI5PrA2hlFZb1zvM5EQC8u0 +BZQ/DqyShOjypvxldvol6UGjys7wecPxt3cBJC7uroY+nqfxHnOIxRFoJGdC7pSm +f90/uDcX87oCbK/FrzJBO+/V2lGHiByC7ahcP59a4Xd69lHSMtRWquclAyBEy1Mx +p7Bx/v5kCpv14JE6SBlYEwhFrTt4aT49FQEQ9aJFKRv7j20sS/6wxPzGx24HE0Gb +XwusK9jo5skGLLUC3g== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-49 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgICAScwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0ODE1WhcN +MjIxMTIzMTM0ODE1WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEVMBMGA1UEAwwMRE9E +IElEIENBLTQ5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2EngKIwP +Cl9+dsIByO2uONNLKhpnFypBAE+LM8+kekt4/HG6StaU/fmqFTRiVI0Uh+td9BWe +8NXOYrhQRo6FVSxBkLtWZX8Px2IHxiqQ1lnrZK9UlCo8h3MPpiN8VEjH2bP/WSa0 +oZEWzEDKLB5tSKerddc+QL2uEHb+Gfym6i+5qPOLXjV00FY24FdNOyHaRjQTM/Lf +sjWoFItHTKp5B9QogdKnyg+WkAARYtbd1nqtDXv6Fph5HaT39SEnRhc+lkrRDpDY +c+HAU6Xywik+stgv2yFk1MhFpF5/rndEwMLIST0+lSpahJKGmYtg1VKcnDcq5CER +C31gl6Yr7ffjAwIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHIdgXoW +qvLczmbuRcAwHQYDVR0OBBYEFNhnk8pG3MmVppSzBBicziU6lhxNMA4GA1UdDwEB +/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycwCwYJ +YIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFlAwIB +AxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQFMAOA +AQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwvRE9E +Uk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRwOi8v +Y3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsGAQUF +BzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEATmfP +QPkolF5PB0fS/9DrngX0tmdSwlidBtrkY6vL/V7IMKqJk7r+hHW6k9+nxijHFj6Y +J1+4ElpH/PwWPsqwVIshQxECvJKfo3OfN3a8Mn6Hog5kXJl5dMb0vJOpWQ9UhmG2 +m9UUZ9847wSlbW0vMHL0puuTso0365vilPO5JkapEXcFXdc3LDxXW8BR5NHyaN3V +mvfD/qAqe4BiBx2+WAxsolTJQ5IMjG5tIN7WE6VJdUAm6EIgbuFfvG1KiWQJLHkL +XdTvwdUTqX9JQYswfvoCwvHRh+I2mZX+/iH5HKLcaxqW8b9JnHCtfMSBZqLdI3nG +IBw48tRul8lbrg0mJw== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-52 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgICASYwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0NzI4WhcN +MjIxMTIzMTM0NzI4WjBdMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEYMBYGA1UEAwwPRE9E +IEVNQUlMIENBLTUyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw4pb +qFZ5LPm9gcWT24lCj8yLQHYdzntTWgMqPVyveG88rA+bXiAWO6zWUsjPlYQHfxiN +qTZemKgK8OUkVQA4oiQ59EzcNiRsZp1hy7nvDpFcW/0WJzHY5M84ThI57zRH20Ac +iNw1DB7XmR5yJFKTFusipWgsqwWRTtpJlLGJXhTHyG6aNxP6HEXbTLAM4x/0LM9Z +Q2yYihUufgtJYGeLapNb1pPLsPVchhJOQjLFyp3Kx9W1xfjUFftE9FQAwCBJHyC7 +tFMk6DlITy4s7ptst1nNbPYdzGmiix/P7+I702Yn8H3YbmhFD3d+fkhCXqsjio0y +0wWFDaa6vmm3RqF1GQIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHId +gXoWqvLczmbuRcAwHQYDVR0OBBYEFOlmDFyb4lpKsgM2NP18yab4qwc5MA4GA1Ud +DwEB/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycw +CwYJYIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFl +AwIBAxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQF +MAOAAQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwv +RE9EUk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRw +Oi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsG +AQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEA +dYEfuTkBoJLwzyIZ/lrxB3ECCes2zWMLe1RsRrQ3QUhkeLcqxxwG1z+UbbmWkrSS +JS0Q1XeLRiT7P1x+ycs1Gvoy5V4CFOryb5eNaDpOclJdXOiRjOGvS0wSeSLGnT/d +lRPrQZcoEm+DFvtSMasu/zR8DnaepKpWLvyFXwvoimvsQVvz4tOS2o4u400KLPBo +MQbTwpDmk39wxf4Aq4m8hznf2BhAy20YH6jY08gXg0pNDVh4CZIxyF2gmE0TDXPv +sx77lxYKW3Bx0ZxHIcfBKifjSiTrGlLeEP9LfEQdpCjJqhG/3BFy6flzwJDEHqHH +swhN9DCJn+3xTeq25PUXPg== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-51 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgICASUwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0NjQ5WhcN +MjIxMTIzMTM0NjQ5WjBdMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEYMBYGA1UEAwwPRE9E +IEVNQUlMIENBLTUxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnw7P +Taj5UGSMi8whxGpPsoChGMjVQRk1Fzp9J/mPjx/oXc2MwMahK3xpE3YB86q/SeH1 +Cv5hc9Pa99HtSF/RaHAo3frFoPnRNoPDLj6ihPGmEWwMKywUgOCnTQcGSlNqR0es +tYrMTxti9bKE3uc0hgWibZYlukiGYg0UygYPS4+afMtzaBljiUWeQFrmCaEgeG3B +UvX/zgNdSqtG9KX1LjqtNZB91hIDrRUNohX5xSLxPMpojC5d391u/0GfAEXeKyAy +bPN8BdVjqJ7FlyueVKUgIAB/t/k6NO3lKEiC+QsrhrwaFI3Yme9JfRsZU8/Yhv0L +wKeJhoz3552oT0e4PwIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHId +gXoWqvLczmbuRcAwHQYDVR0OBBYEFDXvECJsuhIPvcJNGeTOfY8FV1w0MA4GA1Ud +DwEB/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycw +CwYJYIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFl +AwIBAxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQF +MAOAAQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwv +RE9EUk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRw +Oi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsG +AQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEA +Y2UKHMi98mslNJ9qUBT8ZNGKim+nYkfLfBgdP136smJYYDcwUOXwHt3b1aOy4sXI +0BkNNS6tO5fdvZ7W4/zYFouIVnImaa8hjDiJNoAi5dYKDxkB8iOWYlAP8TZwpKNy +sbGh4EQHWWQ8wDuFcdA5/9ElnxpQ/JJzSgUOHhtGm8vrEQmmJKW0FvbGXhGydHx2 +I5GtDvGHqlpF8GFIAA5HNAaw1s5De2StEYCTS/y95naqZafCxYG62cGbHir8dp0U +KQOUQt88tTh0TAqzcLKz1OJIoIkbfpzV6XiXuL0VSob+W0peZeqTVq+w7nWP1cNr +44ligwwVjeF04L3sZKA54w== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-50 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgICASQwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0NTAwWhcN +MjIxMTIzMTM0NTAwWjBdMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEYMBYGA1UEAwwPRE9E +IEVNQUlMIENBLTUwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAorU5 +fwMKXKwK4SrttozvWb8Zx9g+7pGrzD+cbaZbISrTvNTi9MhDYASMo23nzG/ShHQM +c0qCc10AVUqpAfwRhm9FbphD3r30SWKQsrKeObBW63iMeB6gfhg/+zScvkJxlqj6 +x5cHglMCFQfdqjgmjtcuWIGr7cDf1WQJLGfCz6ilKH/H2no0a3AyoFEAglrUyhC5 +n0IVsmyrWY4Hy9A/0xe84hl+68cJfB4VD+8A+YrUqEgspiqzocvzcuN/GNdeD9Lw +XPqylqnF8SN0HYoHmjbimscIn86wCxARO0siWZ7hStrcbkb+cgFoY5aScdldUkni +YI2cmRy0C5jv+wAfXwIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHId +gXoWqvLczmbuRcAwHQYDVR0OBBYEFGUKe10mGzDKLdz81nPHHsF/BIzIMA4GA1Ud +DwEB/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycw +CwYJYIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFl +AwIBAxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQF +MAOAAQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwv +RE9EUk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRw +Oi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsG +AQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEA +VnLKwRdYBaPnEONJnTpHoC4znIQMHBsEpQbR8P5j49IXtHRjCpl5PKRIwuAc+Ff3 +ixM3jv/G+LBi26G0ZNGZ4iI11rJ3TLxUqHT12/WXTuS91jePA/f3WIHkGBEFeRs+ +wiROXSAveyMAt1ThK9Bil7BYlLmpgfci7eiKHC6OlA7VZo4OrS03VZTlaaBaU5Te ++tX8XYQ7Kllh9LreXZ2Cks14oNBlS4vzOcZOpw1bamaEbIA13IsGyY/kF7LqSPW2 +b7Jy628ObLeU3a+0lm+nIkjH25FDvtfxD9+2qQHEpRaRclskwIGTmA/Tg/YrrS2Z +am9RD+6E/tsgIIlQE09NEA== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-49 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 3 +-----BEGIN CERTIFICATE----- +MIIEvDCCA6SgAwIBAgICASMwDQYJKoZIhvcNAQELBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDMwHhcNMTYxMTIyMTM0MzE0WhcN +MjIxMTIzMTM0MzE0WjBdMQswCQYDVQQGEwJVUzEYMBYGA1UECgwPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLDANEb0QxDDAKBgNVBAsMA1BLSTEYMBYGA1UEAwwPRE9E +IEVNQUlMIENBLTQ5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAus23 +xtOAbfLxPh+OS8U3N/c7ZsnTNZGki6KjnEg4EVHnUKwBB1pWLeQbZTVp01dHWlxR +KyvANnk+8ozM8tucowx0q6fo5J/YteD9qHFAoWjJQpRB6Hvn2vvHvUbu7iAY5Pel +0B6A0NN/lKW26tTlim6NkV1MuCcvpCGrwH0f2TOCzkDf7IPqQDvLWOjPQP9nmNMG +nS+qCvF5F0iGFXTH1NDeI8EPvKMBQE+LgJ4PAF8eFdDo0mDE6iLfPAIXBzfYUdFk +MS3eVpJOWPzOEYeRLcWQkORvczfxN0obxSH3TGoBLB3ubELOoiqgsTF7rLKE1Kyz +Wrao15uoYf29O9jatQIDAQABo4IBhjCCAYIwHwYDVR0jBBgwFoAUbIqUonexgHId +gXoWqvLczmbuRcAwHQYDVR0OBBYEFGlEHxqVTqUaf4g6zHsSOSwfzxoxMA4GA1Ud +DwEB/wQEAwIBhjBnBgNVHSAEYDBeMAsGCWCGSAFlAgELJDALBglghkgBZQIBCycw +CwYJYIZIAWUCAQsqMAsGCWCGSAFlAgELOzAMBgpghkgBZQMCAQMNMAwGCmCGSAFl +AwIBAxEwDAYKYIZIAWUDAgEDJzASBgNVHRMBAf8ECDAGAQH/AgEAMAwGA1UdJAQF +MAOAAQAwNwYDVR0fBDAwLjAsoCqgKIYmaHR0cDovL2NybC5kaXNhLm1pbC9jcmwv +RE9EUk9PVENBMy5jcmwwbAYIKwYBBQUHAQEEYDBeMDoGCCsGAQUFBzAChi5odHRw +Oi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTNfSVQucDdjMCAGCCsG +AQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDANBgkqhkiG9w0BAQsFAAOCAQEA +XDNkaD2Gwe4ZoWklwvAvveoOYK5s8fJbjZOjI2V1tZjIP5edw8YSvLDGTqsaDlao +28hCVhoOU0+V234p0CAGKNKID6WCR46s7uAALaaWfd4aHDzf20qYsnMrl0eKCv6F +sUtKBkIYJBjxpoaIpudRCnSmQkxweKzCGCtjWCT2MGSJro2Q0eQWTDxnJX9/v8z7 +dZ8ddZO1zgoU1xnAx9LxdrVl6H2VcB17z6t2d5TqSLM/OnuSHT7LWqYbVJERf38D +U0WSQ7VOp2x1SkInJqpewvi+0rl/yh97UoDZuS/GUkVIMFbpJkbcadiEGBINErRl +R5vQZDesBpGqUxNYuIIJbA== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-40 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuDCCA6CgAwIBAgICB8QwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUxMTA5MTQyMjU0WhcN +MjExMTA4MTQyMjU0WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEVMBMGA1UEAxMMRE9E +IElEIENBLTQwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsC0FbWsI +la6+NfHD63GReLt85F4jdzs5mlNrXkjVlXJzksaIkmlHfqAWyo6ea8ShhqwdNnXg +PlIb7ej4RoXFqXJIwsCrxQ7rev+sCdkL5UtxOxPq40wbjV+AcjF8Qmp9xoPyImxz +lLebWWJ8HDgJl2HSLrIFibrRFeD0t6GLsT8JhOdQmqE8wRNypZH6oDIhygX3lhBe +RDxuK/6zLMJ+srqG8DMJFJhz0kHh36ugbJJOPLyEGxwjyEicBqk44NFcmr8YWC24 +RM28QjruqwotlsI3woCaTHkVm37fc0xmbAPg4eggxrzXn3dFQE+cw40WBLpy0d0G +05PMAC1LKPdccwIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFM1bl5X91Ceq5yXxnIfW +8gfX0Yc+MB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYDVR0g +BF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETALBglg +hkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUDAgED +GzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RS +T09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9j +cmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYBBQUH +MAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQBFRhX2 +izaXm5Yu4omDw2mbNo59EYAaITQCcUKbK6pwkmRYICu8DsjLMVhciOgeK4fn4OFA +mYbLXWAtgSknNc+Hugb4WFoLWSb3EKZs8ocb/fR4eJLOKoY1PuRCuozS4yZFPet8 +RFInX8l7NQ41Zyu4O4QNzmcMz4pct0E+7nOisGEjh7/29Q0UmITPek60iVGEBIzz +skjlclPzu7+qJseMF+cIV+DU5hFtEjXZ5HPn4fS2B/Fa15vkbnA9MvkxjFYjgLa6 +Xb/3zH5yYN2b20FluCxWyWD29UKXS5vwnXVGn4d+LIt5LPXbkgYt7uxgGCIkX2ha +hR0L51Yz9q3/sVvm +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-39 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuDCCA6CgAwIBAgICB8MwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUxMTA5MTQyMTU3WhcN +MjExMTA4MTQyMTU3WjBaMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEVMBMGA1UEAxMMRE9E +IElEIENBLTM5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHukMtcV +I9MuUvhC55JlteAPugFH0iElnuOH1uST9FQVwCueIgZEXFQ1HtQyK/N/Dt2nM89Q +FT6lJ55kAPhJtqYpGZYdfrirxWRTNzisQI2GoDTzID9iMYxd4wTikDvuTpV4H0s1 +sU6r9UqdouRFMZ+PrClHyTji8P9PrHY6+YSSLXu76fJgfKNdDBtIGaUhTA9CMOXv +TJGJLiZTuViJobP9hAEWtgd/8C2GIdTwbQPb/R7fsM/joH94HX59A00Q6q2COz1J +G6LB/GqvfIGpIx2NmLx6beRDQ1OpCs3mzqUTXmfQpZD6vweTXkyIGqlEgav5yahv +vjm2Pp7O3VjbEwIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFKrDk9xwD3lROQQd5f8p +6BbIrpPGMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYDVR0g +BF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETALBglg +hkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUDAgED +GzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RS +T09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9j +cmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYBBQUH +MAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQCvxzdd ++7fyM+exiin8pLYIADkJ4pUEnO3xxayqEviFgD/kqy6VInSIWP+eajXsTAHQwsUi +aV9i8ba+ejpZpkU83XgyWR873P0Vycg4o2pUdx1jhXzoMqEq/iZBvV6SEKqHRmK3 +8eZ0mzAevAE8vEfr8o1RtwoPO+4Uh6pZpBcj4NWYgL9l+CDotlKivAMIy0nN+NFJ +4SqPWXODhmFlBsCtGY0sJWRWn9sGi0kaEU0sOyqfSnGwchTS34D7MuaDYk7Usgx3 +Sto/Cpp7scmHsVq56evon9YHVxclT3NoWKy9HHxsMIjVVAEGpXOZ05LYW6O02Eds +oZ/0UDsa8A8aV5aL +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-40 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgICB8IwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUxMTA5MTQxODQzWhcN +MjExMTA4MTQxODQzWjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IEVNQUlMIENBLTQwMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzNjg +O6XMNXsXqOPEk9Q7ZmS8o3JNb1NhmvC5hpfRuA7GUDT0eFJYt0uWgMqFdSvMTrRs +JW86RfWnuAz9dnszgUPcfimp+6LNy3yEb/NUWQXiiYCKmuDLo8YWkkfzoMIAzVH+ +Dy++wzc7lOngm5ZgDzdVuGd/QRQ880HyJ9HYnJFkMT9vXvlbYDN7HopIWJntpeaa +tqudwm29Iz3wq6/wba8tDd6aWnOwfRfL9uCe8EGuw4xJh1uvpFfMq2N5GhUIb6kS +q4gai+t+b2cfNJ2OIwKQnysfcO5kJne1Za4oI7GP03IDtRyygvBANOTrBnxKUhMX +MjbCxRxNGm6/GJCz5QIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFJuBtqJZi+3pgB/w +Jz1XBT6JL7bMMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6 +Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYB +BQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQAv +ty5uG7qcbmzT2hU1riC3WUF7fYN6qCRBGRe1beziZqr7NWsJYUWDu9iIvHTRsXdI +SgYgtqseBl9zCmY49iyXWBOs26RF6CyVOOi9cDPMzzuXHfsrFRrlgotvgI/IxJkt +DH41GbkFmx/yZXkCd8wEM5Ud7Gy61zquEvD1qsYM8qUuDCcT0sB70njKQ+ETKQBW +uQdqRDyUSHbnFZaHS8/uGpCL93ie9vVRJEBuGl0fgJXblXDcJsM0YOVgLImGCxnk +lfWCaIA7QtkWmd249PPR+KgM0WW+QXHLEsULo5iUrZxOgPUoo4auLR/Alk4KFmql +8AJej2z9iMmg6Jb1BbG1 +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-39 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgICB8EwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUxMTA5MTQxNDQ3WhcN +MjExMTA4MTQxNDQ3WjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IEVNQUlMIENBLTM5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs/Gg +vdig7X8ajfgi1iqHWM3n+GGoqt9cQwGfORbowgjHwIDb7tNQqMPRG2pVYSlST5nl +Nkoe+XRTI/vhExMRYvTDkBmxcFpHAmi4lVFeYHfGYvYn7Ai9SndbTlK4G8tx9BPu +rYjrI7z+TYdlNfcxcqU9Zus3L7VSjo4Nz/oGu1QPdZ3e5W27mrBrGVodhYrGd9zb +vclzDGKpANfrrF6Wm0/t07/j2opYuXDrp3CSVPgHXRCLueDJ+xyIth8oZ/uq7l1u +O2a+4xixCQpuGnTjVfBkC19jSG8WylKn8crduVPLCmRTp65IXgTBAV6gpjta1veA +8+hFLGswsSKzVTy2YwIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFKyd+MRMc6BDXwgl +fUYPZRvLoLCAMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6 +Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYB +BQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQCa +8QoBL1IVhci+xe1rnO2hJlMnKKWwsRXmxC0qq+sSqdEcq0hmwDFlQeKyI7hByp60 +9J+i5yhu5ebOHGsQuU71/ENMAMOczUYt+MYJocGcwe1g1b/XZtZshgo9N6Gwrlny +WFwbr5CnX6yswooBmUl0xdYvcd/ZZ6/5djuVUu4n6/bIwbWcqkkyEDPGGFNXxenT +DuS3BgRAaggyMcNhQNdH3gcc8DbQ57lB57uBNO0cHcaVa2Nk+TGt3eRoLTeqNHoS +4ZQbg9v4OhAZJtwhKydCtxZAcHcxL2qFXMiT2ots/NmWZyS3sJqSgWcz77a2xREb +is7L2sM8/f9lDnpymyuz +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-36 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgICB6EwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUwOTIzMTM0NDQyWhcN +MjEwOTIyMTM0NDQyWjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IElEIFNXIENBLTM2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtnkW +Y6AlD+M3jiVf9vhsodsLFGnoiYi3dQoseibOrPSU555Ft/5GHGmj+nCXW9twRmGp +AckwzWakNR6nyDh56c5OhJxWKEg594B2i9SBmTXicTzBPa3tZNoJh6Ml6/Ofch+G +XR9u/FFdDWs7ubEF2K7u82MQUsYif+tePRAssI0CToGPF5SPw3+CcijFwY73JFFy +my55gZtb9jiEEp1aWrIgJ9nJczyWbFOV15I5tZPQiWlaXq0BGFh1hJiTGhgGs3fZ +H+yqMmOL91Msb9u99TAr4R4A6yDV/s313JkV4kWIJ1CNSPZHsXOY5WXj6zq/CDhM +JqozUbreJREFadAfwwIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFGcaNjy6u2+FA+cj +iK3FZ5ClTLqEMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6 +Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYB +BQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQB7 +r4RGlVKvdqeCAoErpvW10WRPIn4mmMJbOwzwfgLPzGKvnNQR0CWPWgb8Y7QZYtIT +cbBcWE8awZwB+OWDgTOoxrD0+euOw2CvZg36Z0P7mbS4IF6ElxDd/tzw5Hqr8vkw +hH/F2f6k7+tRznt4+cMQwJmIDKGwoZ+3Atd7CKcouBzXZLcNEbbohJF5z54EYwRU +J5agPcnTZMBDkQfSs9ku1nPrGQfATEBybLTAe31untM6oMzMHw8PYn3Sh7xWTCDG +SFSnPYhzlNKdMb8BKi3spVOxt6t3VHzNXDo8FXRbNpBY/fS7RAmHPPrz5pa9KNtJ +cKENmIqQ5QbjB/P8UX3i +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-34 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgICB6AwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUwOTIzMTM0MTU0WhcN +MjEwOTIyMTM0MTU0WjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IEVNQUlMIENBLTM0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl9rP +JyF3FMlTkbUCbyRbHPGfd9K7RKdmnCE257ehsNm7nM7Q9zxc8SpbTSDbOaP3Wqov +S5bmsSE+leWR/MhTGV4VMKztZmkGea8WYd5zooz+OrmfuoxEoCy5Ciya+RT+wLOw +H0ApD4doIkrkZd2Q2ZJeL/8pDDj1hPAMLpTfJbekNsQ3hsWnKp7AWVsliY4lR8u0 +RYmX4LHYM5hN+qf6uiOLK6U/pcXcyRa3ymxiqq0gkVKqzybqKjlF4JucUU9zTc/R +cm2XSQEFl5niGI1YRRcrwGdl88TEYqcD8LfqAfKtVHvKy6nQ49L2S8qXQi7p9DmB +bGf0c9gZFxG2SAo19wIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFA+GWX7j+ucT+zE7 +wTkMfGCLQMLdMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6 +Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYB +BQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQBU +9C9y03/5bT/I09cfBTJDhgP5zoFm45xTzfA47ENg9zj7VntEUG9KH4lkgnIxrD+p +hx5kGZgpxK218MWlQKWutYtrFeeS+RBisyVEGEtF2JjYEmQ4dUAOfVEy2iE/6jlg +7JWB3nPNCVYjWsvYAwrtciclM/xdAbuBm1valn5TFGwp3UQNMfkbiYs6luVubPmO +760ruzCJyDwcOopbraZJ3BNqMVbPHL68axpk8mKE83k6WgqMYIEsolA2F95OSPuB ++3jjC6U0fehSz5Ud4xmFdFV4AiW6mgCYy1RZxwPO7HovxjRs+tg8UtwcOjnVBPpM +5Qh8+8BEUs7sjKlow1tH +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-34 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuDCCA6CgAwIBAgICB58wDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUwOTIzMTM0MDMwWhcN +MjEwOTIyMTM0MDMwWjBaMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEVMBMGA1UEAxMMRE9E +IElEIENBLTM0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz7At/wMM +qpI56sRrQlphyt7hTUYitQma2jYHROcUqaROcqW7Q+sZQuH5lENLlRP6xd/mIYac ++w390E2kPbMQwA46yb399LTve7pJoeukdfNUhgLtBJ1R9Kg3IRJhgr8J9vnY5m5S +y+MsGKhwA5XHcGtJtC0NiKYuxnqZpHpa4pDHNFaRQFl+nka12K15qxPgyf6+ro4m +LHJcD2Mk/KE82ETlBgI5TRxxSVLeO9PnFPcNyLMxD2IKe/1zdoHTpDU6lIEjln2v +22QN2Ibr1HBwOACwITWeMMr9tUg2fQtIBzLkybJbWxgo9J5kPpoqQih2Eo6ZKky5 +dSdcuOQrwr2OYwIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFBgkTL1Wlo/EyOP9BWWL +mIjjiHDGMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYDVR0g +BF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETALBglg +hkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUDAgED +GzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RS +T09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9j +cmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYBBQUH +MAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQAGxypr +9mbQvdY2thCJ3ANDuIn1MK8IhiX3We5joBshmTcfh71DFKsNvUps4BPdjfNGcHng +CTlgHwe4MEsNzUpSkD3e2nm7jPriXh4tRL5RJFEK6yxDL+k3LTL0c/gVjjhsnZoi +mr2a8JoWyDUVdUJmHly4M6GtDWw2l6CiEro3Lv3pEuURrgE+demq3WMhb5IZw7+N +Zi4GapdONX/a+e3028H9KVOC2IbfH9FZGhL96g5YtASd+twKydAen61NE49wYZqZ +rn0E2PywQSqZjiuiEM9F3QNzGVd9geux4TIYvzyQl0ywWkimZlCQPkQUe/hOUdZW +MFJfAy8EW8z4XsPc +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID SW CA-35 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgICB54wDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUwOTIzMTMzNzUwWhcN +MjEwOTIyMTMzNzUwWjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IElEIFNXIENBLTM1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAivXY +eDP8GJB+ao4zla/UEtJDKEflwOSda8kGxkfbz9mMLQFB0iamHa+g/ldgulIUr/pr +upUb959Q2i26GrWHRozgWniOdLU6/X4ZQnic2cM8ejit9TK45jGmr9Krk7+Gvt+i +XtDHTVAQKyVJOKBZyexFE/zBeGjEv5d4tnLy2rjqrgfskXTAYTBJfOkJvHogmuP2 +hrMcEkC/b6LYAAFy7obVdmZcv7B9c4brzml6ZdW/Hjp/S9Z+qY+WnDr+hnbN0Oc+ +qxAaxZxY7kMBMBCEMXH9wBnGFEVQ0CFW918zYKXaIDizkcMCC7GlORKGnQh3gxKn +r7NOc5mSlVK6W5az9wIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFN7CRmPJB/WsEhyq +mREdH+pT5lQyMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6 +Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYB +BQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQCW +F8rvKyx7YtnMtonV/LyPXUHpCnFbGeg8drZ7qNKLVxxLraVBSs6rQz1XiKTcyzpu +zYfPyDIHvxaugkJg3cL/oruKJ3GZ/wxQdNzcljfhAcpuz0BCv3nGzHy2khAoFbds +ZbjTeeP189okGF8hV9Wv0jImfvgAyQJV4Sve7KBQvwwBJRRLA92WTPmkbSi/LtO7 +2FyOiuoaRA68xmptPiL1xjap0fHJfovs6imAGl8DuVERDsuPiNoQzsDDkPaNQ9j+ +/sAFszlaatFIBKTmZ0hWk9PHnSLb5vlP1zyFJuUSK6Ab5s0jWUFed/YGCPalQSys +aBRL9SJlA8HhG84Ywl2q +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-33 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuzCCA6OgAwIBAgICB50wDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUwOTIzMTMzNDU3WhcN +MjEwOTIyMTMzNDU3WjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IEVNQUlMIENBLTMzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwSKS +bVjWCG5J6MNxhYf1FAiXnHuZFVMZ0b3XTV9rE944yOfKBGT76dCBIAvegMB2HqB2 +ijX/ME5JB6o/YKHHq1DfWTKKiBc++0Pu2L/5EGQfqMMEr7e44hmydzjVrIfM+1/s +wV8C+kTqDtK6CnQio/E4sKnALwcMKi6QhdNotGRuHPQzYFvu3CXWhekic6hD4rFK +jKKhi92f00nMGs2uKtkHZZ/zfqZqi0B1ngDMIO2nklz8MIlHtuyy6aVe1kjd7j/z +7rYBISC0u7MtH7nDWXTS9H/jer7/NPH6Jv84euHwYZoiW+XJsV+n39N6fUz6A3DH +VEjdltOveeCBC1LI8QIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFBVlzf0tkBZKr/w4 +lwDc6kOw3yCXMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6 +Ly9jcmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYB +BQUHMAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQA0 +aN8RNdEAXOx0WqWKmJoBt2y8LJv1EYbhSWoUP+U0OLTPpkrz0nH4/vR/EYtpkbHV +KOAlXWzlyCigMI8spRUKuAtpyq4BFE4kppL8jBc977oLPTFu/Xw+Hw1U2W07fL8n +VbxxYQZltrMu6yYztK/GuNpXnSWD17ZgtypvkefzttygHUfyVTqMsYBpYWncSu9E +ju6VtYJVikCqDfevloX6tX+4pUPsyyxkUMe0xm8YvO4iN/OX3ABW0IGPtGxhIMWz +/aE9BFtgUY45gnpcAagoqN8I1FYq+zaeflPb0h3yevoypAzRqAt3FftEXDHlcEdj +P6LrZrEWHn3iSLihEODb +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD ID CA-33 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIEuDCCA6CgAwIBAgICB5wwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTUwOTIzMTMzMjMyWhcN +MjEwOTIyMTMzMjMyWjBaMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEVMBMGA1UEAxMMRE9E +IElEIENBLTMzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx3397Vyy +U8iwnti8z0835m6o5N6b9ZbPg2AwbGZsBHEA0aW9LrgWqVNdRrFN+L73IVfYhrpd +B9SO72ZGsBfekTPAK4/g0WPwoxDeO+jpBDDbrp/mOrxWlZseY6jpSvETmYdBHuql +dnh+HbnuM7/c863NrUHZvq9T5+wEJekvhJOkta92+WPQhTmoRGDz/C0k7EYVIxWB +XqNDSqbb4eT+9kavdZKMuALhV/Qvij1UC7EyxYGT5GPclNvCDtRxmo397vmiZMpr +LuXqy8DJNnQmQfRSEknYRG13+UAQsYs2GmBc2M7nUXhzmfmAjG3DQNs7F6D0mwym +PurM27FE6rQx8wIDAQABo4IBhTCCAYEwHQYDVR0OBBYEFC2O2dSD8uKQjEufb/lG +52pLzbwnMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1UdEwEB +/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYDVR0g +BF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETALBglg +hkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUDAgED +GzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RS +T09UQ0EyLmNybDBsBggrBgEFBQcBAQRgMF4wOgYIKwYBBQUHMAKGLmh0dHA6Ly9j +cmwuZGlzYS5taWwvaXNzdWVkdG8vRE9EUk9PVENBMl9JVC5wN2MwIAYIKwYBBQUH +MAGGFGh0dHA6Ly9vY3NwLmRpc2EubWlsMA0GCSqGSIb3DQEBBQUAA4IBAQCzqB2z +CqvPEhgEgFD9/ebtFDm6a3c5JtW+1GRgvw2Bm0rVQ3NNecr+C1YnwTv4fut+75rd +a2R77MDyszJYzM6i0nO6f30xm5dGKPgGS7HiPD3Ph47XLY/N+cuAj0mowXCOWK56 +n0uvXU5DKxrAeqlbaUOYakyCw67Pzz+FBNSWlTxrjEkG8rqzUIY7VXX8MtectJ65 +rahntartTt+gsOzECELWFwoRvPzV7pUrY9VSnKR8sjusnxK4J/b0cRk2RblXUe3G +Un9fXfDDnUQ3CgQtbScfDWOeAbPJdLYWW75YSzsyW03amrOi2aBJZU1E+7hvJkm7 +cw8ckAW5tJD5SRim +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIDcDCCAligAwIBAgIBBTANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQGEwJVUzEY +MBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsT +A1BLSTEWMBQGA1UEAxMNRG9EIFJvb3QgQ0EgMjAeFw0wNDEyMTMxNTAwMTBaFw0y +OTEyMDUxNTAwMTBaMFsxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVy +bm1lbnQxDDAKBgNVBAsTA0RvRDEMMAoGA1UECxMDUEtJMRYwFAYDVQQDEw1Eb0Qg +Um9vdCBDQSAyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwCzB9o07 +rP8/PNZxvrh0IgfscEEV/KtA4weqwcPYn/7aTDq/P8jYKHtLNgHArEUlw9IOCo+F +GGQQPRoTcCpvjtfcjZOzQQ84Ic2tq8I9KgXTVxE3Dc2MUfmT48xGSSGOFLTNyxQ+ +OM1yMe6rEvJl6jQuVl3/7mN1y226kTT8nvP0LRy+UMRC31mI/2qz+qhsPctWcXEF +lrufgOWARVlnQbDrw61gpIB1BhecDvRD4JkOG/t/9bPMsoGCsf0ywbi+QaRktWA6 +WlEwjM7eQSwZR1xJEGS5dKmHQa99brrBuKG/ZTE6BGf5tbuOkooAY7ix5ow4X4P/ +UNU7ol1rshDMYwIDAQABoz8wPTAdBgNVHQ4EFgQUSXS7DF66ev4CVO97oMaVxgmA +cJYwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBAJiRjT+JyLv1wGlzKTs1rLqzCHY9cAmS6YREIQF9FHYb7lFsHY0VNy17MWn0 +mkS4r0bMNPojywMnGdKDIXUr5+AbmSbchECV6KjSzPZYXGbvP0qXEIIdugqi3VsG +K52nZE7rLgE1pLQ/E61V5NVzqGmbEfGY8jEeb0DU+HifjpGgb3AEkGaqBivO4XqS +tX3h4NGW56E6LcyxnR8FRO2HmdNNGnA5wQQM5X7Z8a/XIA7xInolpHOZzD+kByeW +qKKV7YK5FtOeC4fCwfKI9WLfaN/HvGlR7bFc3FRUKQ8JOZqsA8HbDE2ubwp6Fknx +v5HSOJTT9pUst2zJQraNypCNhdk= +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-32 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIFUjCCBDqgAwIBAgICA6IwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTMwMjA0MjA0ODEyWhcN +MTkwMjA0MjA0ODEyWjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IEVNQUlMIENBLTMyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo/qq +hsqKGhsDTnFtQbbZZZpu/zYqPwLTfJVliFqk969jt1LHGvu7lXMHQmGLSqZ76VYH +NhuqNwIgHKTO+7bQaav8OEzI20ZW96JefucxtO7B/81kv3mCQSt30vh9q0yP98Ye +PPiOLz0Ug9qSmAnY0MZaWTaLh6KJ3b5KXsvNtkd+QaYJVGxBlnRbBsPUwS5GfV42 +342iRnGsSrrEsffJFwov3aPshCHPqAXqueMub59+fbsdFnVPkh0D5hE4mDZ6odQA +PK0QWK8VxzZL4zubTbW0kL6tq9PAhLP83BWICYwRUFAv5HDstwquSlPiNsQFboB1 +Eo03RvJLDDgcSR+sgwIDAQABo4ICHDCCAhgwHQYDVR0OBBYEFAqwqjhWR3sWfb6r +k5a8VN2F++0sMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDCCAQEGCCsGAQUFBwEBBIH0MIHxMDoGCCsGAQUFBzAChi5o +dHRwOi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTJfSVQucDdjMCAG +CCsGAQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDCBkAYIKwYBBQUHMAKGgYNs +ZGFwOi8vY3JsLmdkcy5kaXNhLm1pbC9jbiUzZERvRCUyMFJvb3QlMjBDQSUyMDIl +MmNvdSUzZFBLSSUyY291JTNkRG9EJTJjbyUzZFUuUy4lMjBHb3Zlcm5tZW50JTJj +YyUzZFVTP2Nyb3NzQ2VydGlmaWNhdGVQYWlyO2JpbmFyeTANBgkqhkiG9w0BAQUF +AAOCAQEAD72PR/+5yb1D5c6+tfM5y0UWWaPftlIkPAlVS9m/lXq9dtngMIfNSqmj +LZ7ZKATGlq4BFIDQJVbxWANV79KoIlKrge8A/q/HSdKMIC6kcYH3JssOpW3VQXd7 +LTO7m7N8nD89/8LuefKJChCMkHRdNGdwvgL+gEYZB859L5aoxBPQ758psTSpuYyl +iTSzjD5H+GaMkdHuq8HqcYXJX7Cp7tsA1DAqQs5XYxAiMKichkESXb5QfBP66yhz +X3IziV9/DWikPf0WJugKk/57H4aBgCe+Z3GGG33Hb7epcQHGY7NzfQFrMyLteYmK +DuZyAnM3P8sxge2k+wtqO1KEukz3jg== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD CA-32 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIFTDCCBDSgAwIBAgICA6EwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTMwMjA0MjA0NDA1WhcN +MTkwMjA0MjA0NDA1WjBXMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTESMBAGA1UEAxMJRE9E +IENBLTMyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs+KVHZM2LSWl +Dv146e/qk9E6ydhXvRnf0cei0ejZ/dKOFajdvT5k9Lb+nAPfS7Blt6sEGDIZbBMB +UtHmtchBEre+O8tNQBCIyp62/TV3bSb2ZK0RhwypJXpYn7C9mPaTXxvv77KXrfgV +59zmoGp1DVHfVR1oQVJJLsecaFdWR4/e9lIugW9WvAaJEpSfI70/gceGAnUwXjOh +3OETu/15VgE8Shn0LOuQZGTX6AovUYbVCJuE+/npi0LKZdKQBxyCl4xEI1cGLHVp +KHCy7T5M1eOWdxX9upXPW5ZpAnfWgNmPhynj5wV2r8qNEmA0cseznThuTJYynpA1 +rXWL0WJACQIDAQABo4ICHDCCAhgwHQYDVR0OBBYEFC/Kk1MDrG919Xb6vv6O6hCL +t+eQMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYDVR0gBF8w +XTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETALBglghkgB +ZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUDAgEDGzA3 +BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09U +Q0EyLmNybDCCAQEGCCsGAQUFBwEBBIH0MIHxMDoGCCsGAQUFBzAChi5odHRwOi8v +Y3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTJfSVQucDdjMCAGCCsGAQUF +BzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDCBkAYIKwYBBQUHMAKGgYNsZGFwOi8v +Y3JsLmdkcy5kaXNhLm1pbC9jbiUzZERvRCUyMFJvb3QlMjBDQSUyMDIlMmNvdSUz +ZFBLSSUyY291JTNkRG9EJTJjbyUzZFUuUy4lMjBHb3Zlcm5tZW50JTJjYyUzZFVT +P2Nyb3NzQ2VydGlmaWNhdGVQYWlyO2JpbmFyeTANBgkqhkiG9w0BAQUFAAOCAQEA +MI3VVmO9mQaLTbbSDgO5xoTSm3dBGojS/8Pa4uZnYb3Zeu04OV6rC1g0+droYnmv +OXLzSqfjTjkQzenSCOrUnpqnNTWTkwJZ4kwAHPP8ayFTSoxh52HL0EYL0T+cafXv +UIrwQLMrVloda2JZBbOPJxgFCkNbAu/dUl5bwKkcVuOVbJdPAYNWcl3XfVHjWlQu +uJj9ck4lj4sW0bDhM+OSfBBVMyRmrw8zBlNIA4eftGR0tdI9InK30Y43ERM5357n +0AwLilkRMmX/9rlGvT82nqeUAFfwwBnhLNxM9y9MkB1D764I43OeOr+Z7CK5B1iu +2TVSS1G7gTaPn24hCqaOhw== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD EMAIL CA-31 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIFUjCCBDqgAwIBAgICA58wDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTMwMTE2MTQ1MjQzWhcN +MTkwMTE2MTQ1MjQzWjBdMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTEYMBYGA1UEAxMPRE9E +IEVNQUlMIENBLTMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6K4C +LEBMOlLoi3OStHfnOEvA8KpKGFzH9zXDSvDwlnell74n78REIYDqFjS3MNFEOH8q +zgTGkWWpblB8yE7+vcC1SxbkOFIV27O391M98rEH25FmXcG38ndmxFGaY5QRSwId +DUt8swBHB3kY+nizkx/Udm2ZBMUeNkb8BjQL42hvHnyfLM9huEv/tN8Gn6BflF7r +Nf8JXTVAB/Kd7ZYJ2Xbq/m4x/sv0ResweEhobKEpPoZ9k0FK6ucMTOWRUCqlQ2a8 +IsD8Gyzk8y9iHgTUIb+sHyZ3NdAdvOK7RsLy6+QUrviza7P6cTiwcSnt0Ysb1wIb +3srsfu6h3Eil8T6UqQIDAQABo4ICHDCCAhgwHQYDVR0OBBYEFIbxW2hv3TDzlIJo +1Ez3RB24ymiBMB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1Ud +EwEB/wQIMAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYD +VR0gBF8wXTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETAL +BglghkgBZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUD +AgEDGzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9E +T0RST09UQ0EyLmNybDCCAQEGCCsGAQUFBwEBBIH0MIHxMDoGCCsGAQUFBzAChi5o +dHRwOi8vY3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTJfSVQucDdjMCAG +CCsGAQUFBzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDCBkAYIKwYBBQUHMAKGgYNs +ZGFwOi8vY3JsLmdkcy5kaXNhLm1pbC9jbiUzZERvRCUyMFJvb3QlMjBDQSUyMDIl +MmNvdSUzZFBLSSUyY291JTNkRG9EJTJjbyUzZFUuUy4lMjBHb3Zlcm5tZW50JTJj +YyUzZFVTP2Nyb3NzQ2VydGlmaWNhdGVQYWlyO2JpbmFyeTANBgkqhkiG9w0BAQUF +AAOCAQEAWTKtqsP435xknHEJNMG9vGMAHi3b7anICOO5GOSvyq4Uwd27+XODg1eO +lMmgqgMHzmecteUXWT8ouBc22rqNw5YRAWpQ1gbaaKRK0guFfM2I3/9ed+b1pEiR +0E6iZ2r4aO+qF0Xv2JYK3c/wPoe2v4g/01S+PhLOofkLbzLRVL+EWzWg2wdktavp +eR7i8qp0cueREvfHu27u5XSQECSLt+fNnIWQR+Tib38gvSy7g5YjTahM2H4uXhUp +uCV9VzULLRVUjKnc4OU3nahPIJWDK8USNj2oc+FOiEmlubv6CUooWjO55JJ5W3v4 +pU/zyTTNmYywumB+n4Q+5jz6flrr5g== +-----END CERTIFICATE----- + +subject=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DOD CA-31 +issuer=/C=US/O=U.S. Government/OU=DoD/OU=PKI/CN=DoD Root CA 2 +-----BEGIN CERTIFICATE----- +MIIFTDCCBDSgAwIBAgICA50wDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCVVMx +GDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMQwwCgYDVQQL +EwNQS0kxFjAUBgNVBAMTDURvRCBSb290IENBIDIwHhcNMTMwMTE2MTQ0OTMwWhcN +MTkwMTE2MTQ0OTMwWjBXMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zl +cm5tZW50MQwwCgYDVQQLEwNEb0QxDDAKBgNVBAsTA1BLSTESMBAGA1UEAxMJRE9E +IENBLTMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxicQL5CWONnf +5l8/uon7ZoLrtqXt8FaQFkDnbKKweWZZ15hiMdEzIlPjHlykVmamTVb7w+JCEqv5 +wEpLQO+RE4Y5MFHWbo4nt0GJKQHuWEZzBHFEXGlDPjLmZN+za5kscKLQPk3YWBJt +RfA9k1S+3+L7zxH//IoBN++nLrpADGo+HOQKMoBpvSI57Et2ybFakzwhhDjdcxOC ++V0MgQqpslN02QuOwOiXuz1fE4y1uTvs9rudjiD2a7ydFDLcfrniY7BqwYC5FvyR +76yyCZ9SR1gTXmJ+mhKGW8UgH+GOZgB2U+znIokhTF+56b6gUpMOpsjezLeCrSJt +i9AwUzZVVwIDAQABo4ICHDCCAhgwHQYDVR0OBBYEFETjRqNB7mCxXqeTJfSgU+63 +Sb67MB8GA1UdIwQYMBaAFEl0uwxeunr+AlTve6DGlcYJgHCWMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDAYDVR0kBAUwA4ABADAOBgNVHQ8BAf8EBAMCAYYwZgYDVR0gBF8w +XTALBglghkgBZQIBCwUwCwYJYIZIAWUCAQsJMAsGCWCGSAFlAgELETALBglghkgB +ZQIBCxIwCwYJYIZIAWUCAQsTMAwGCmCGSAFlAwIBAxowDAYKYIZIAWUDAgEDGzA3 +BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3JsLmRpc2EubWlsL2NybC9ET0RST09U +Q0EyLmNybDCCAQEGCCsGAQUFBwEBBIH0MIHxMDoGCCsGAQUFBzAChi5odHRwOi8v +Y3JsLmRpc2EubWlsL2lzc3VlZHRvL0RPRFJPT1RDQTJfSVQucDdjMCAGCCsGAQUF +BzABhhRodHRwOi8vb2NzcC5kaXNhLm1pbDCBkAYIKwYBBQUHMAKGgYNsZGFwOi8v +Y3JsLmdkcy5kaXNhLm1pbC9jbiUzZERvRCUyMFJvb3QlMjBDQSUyMDIlMmNvdSUz +ZFBLSSUyY291JTNkRG9EJTJjbyUzZFUuUy4lMjBHb3Zlcm5tZW50JTJjYyUzZFVT +P2Nyb3NzQ2VydGlmaWNhdGVQYWlyO2JpbmFyeTANBgkqhkiG9w0BAQUFAAOCAQEA +R1FS3PSgc5pC5wvsI5GNJXW0RII0qvlGdVHD9g745+MvtCDD76FlNOCdh8HmLmLw +J+jrxc81ldJAgIuSCbamG9USZDHbtdQO3wqKtlb1vHaSkxl8v2V9coHYZHs5NIp2 +WMwdQ/cHzxyDA3O+OBfbdK1pCRF87djWAo1mPatryjPbx3pmxd6nJ0gPZhLuaCTA +75HqBhkqUFgT4CL8DrEk++uOQgIPd4gVi+by9VO3fOBVmxPWtnDKc3DjUyXBKB57 +xCxJbpDbqstbAxvCh4f1q75RcXNtJmZ7mx0X4O3jwN4dJ7HtDTRGPt0uXvSCcNrR +kxt53dZK5875P3MfzormFg== +-----END CERTIFICATE----- + diff --git a/ssl/server-certs/dev.cac.atat.codes.crt b/ssl/server-certs/dev.cac.atat.codes.crt new file mode 100644 index 00000000..86b81ccb --- /dev/null +++ b/ssl/server-certs/dev.cac.atat.codes.crt @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDmTCCAoGgAwIBAgIJAPTXTxYH3TyDMA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNV +BAYTAlVTMRUwEwYDVQQIEwxQZW5uc3lsdmFuaWExFTATBgNVBAcTDFBoaWxhZGVs +cGhpYTEMMAoGA1UEChMDRG9EMQwwCgYDVQQLEwNERFMxEDAOBgNVBAMTB0FUQVQg +Q0EwHhcNMTgwNjAxMTk0NjIyWhcNMzgwNTI3MTk0NjIyWjBzMQswCQYDVQQGEwJV +UzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5MRIwEAYDVQQKDAlNeUNv +bXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xGzAZBgNVBAMMEmRldi5jYWMuYXRh +dC5jb2RlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOGjINZSzsSH +MP0e+PxJhuM7v0juaB51UyzEp1tnrICKygQ+JaVLUmvZTiwsILfAFJ0Atxr50nga +CG5R+QN+JAOBJ6v1tKW/NQ7kWCM8tyC5f1aU0rf5Yvl6dhZXJKszOTROG+3Qg/cH +DM57/YrbOBnm30PaEAFD/s13hKEZklVgX3wYyaB2oRmXBbvWog9uFl3PLQBmnCPr +q7aFlr2S3THO46PqHITtijwEDQViXgE+K5wm6ogi/cXzuD4aYq0PVk+6WaorXBOZ +pOWnRyyX2OaJMyFzjuTBKQ80NMivcuh+fRQIhviSepeNuXeyZkWzQtixZPh22/Rv +3lmWW4mY3D0CAwEAAaM6MDgwNgYDVR0RBC8wLYISZGV2LmNhYy5hdGF0LmNvZGVz +gg5jYWMuYXRhdC5jb2Rlc4IHYmFja2VuZDANBgkqhkiG9w0BAQsFAAOCAQEALeJM +LAPCxoqi/RirJcY5beiHZgLGLgolDHJEE8ZzKtuNqJvGWPwrTRGmr+mm31Qnl8IP +M/skIC5CtYTdJRHD3AYNyFOFWmTuDS929mWxg50eZr8xdpS5sQ5AqiBclToXgOTI +qRje/ojofTVl8RdT1q1gH0f+Ul60fywckngtSzJu2EkMTjy1xRCzmm137PakGuwc +IZE+4trl2adE7GVWhYsF+SaroiLMIxFCcJqeqtbPK3OfuGMLUUr20O42fWfZskqa +xenWST0R4M5ixMx1L3mou3vqQxHjihRpCaFDgpVJ0EbHbw2j3gqSiVF7q6N0mxFk +RZ088LtbYUr/LL3TCg== +-----END CERTIFICATE----- diff --git a/ssl/server-certs/dev.cac.atat.codes.csr b/ssl/server-certs/dev.cac.atat.codes.csr new file mode 100644 index 00000000..224ceb04 --- /dev/null +++ b/ssl/server-certs/dev.cac.atat.codes.csr @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIDATCCAekCAQAwczELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQH +DAhTb21lQ2l0eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlz +aW9uMRswGQYDVQQDDBJkZXYuY2FjLmF0YXQuY29kZXMwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDhoyDWUs7EhzD9Hvj8SYbjO79I7mgedVMsxKdbZ6yA +isoEPiWlS1Jr2U4sLCC3wBSdALca+dJ4GghuUfkDfiQDgSer9bSlvzUO5FgjPLcg +uX9WlNK3+WL5enYWVySrMzk0Thvt0IP3BwzOe/2K2zgZ5t9D2hABQ/7Nd4ShGZJV +YF98GMmgdqEZlwW71qIPbhZdzy0AZpwj66u2hZa9kt0xzuOj6hyE7Yo8BA0FYl4B +PiucJuqIIv3F87g+GmKtD1ZPulmqK1wTmaTlp0csl9jmiTMhc47kwSkPNDTIr3Lo +fn0UCIb4knqXjbl3smZFs0LYsWT4dtv0b95ZlluJmNw9AgMBAAGgSTBHBgkqhkiG +9w0BCQ4xOjA4MDYGA1UdEQQvMC2CEmRldi5jYWMuYXRhdC5jb2Rlc4IOY2FjLmF0 +YXQuY29kZXOCB2JhY2tlbmQwDQYJKoZIhvcNAQELBQADggEBAJgWiXenFnBMAL+H +tM3RvgsVXVd5ccAL0tiiRplm88JrtEPylDmN4HG1pp7Y11ziMoZvP5TZBJEVrArw +ONT6VacOs+5UBw9lQDU7KYNbUEZlcCfPBA/cfxdWUgV0pDV/tOVUeB16HOZjIrNA +3s6r2GhI7fnUEWhbmEKe7DvUyX0seMmpMl/E48b7FQ4i+1frhSjH5SC1GwKJLM3P +Sq5JALYUFUdn9yNCMc4tGtRwrJkPoUAzUQRlczJ4KsHl0ma5uAQ+B80H3spWgb/j +/25+mQl8vzLE3m/mVcCGikAapJTyA56EQhxp2Zrmy29bXsWhaR7xzRxWtrIGUXlE +g8vKEEc= +-----END CERTIFICATE REQUEST----- diff --git a/ssl/server-certs/dev.cac.atat.codes.key b/ssl/server-certs/dev.cac.atat.codes.key new file mode 100644 index 00000000..c7ff3d88 --- /dev/null +++ b/ssl/server-certs/dev.cac.atat.codes.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpQIBAAKCAQEA4aMg1lLOxIcw/R74/EmG4zu/SO5oHnVTLMSnW2esgIrKBD4l +pUtSa9lOLCwgt8AUnQC3GvnSeBoIblH5A34kA4Enq/W0pb81DuRYIzy3ILl/VpTS +t/li+Xp2FlckqzM5NE4b7dCD9wcMznv9its4GebfQ9oQAUP+zXeEoRmSVWBffBjJ +oHahGZcFu9aiD24WXc8tAGacI+urtoWWvZLdMc7jo+ochO2KPAQNBWJeAT4rnCbq +iCL9xfO4PhpirQ9WT7pZqitcE5mk5adHLJfY5okzIXOO5MEpDzQ0yK9y6H59FAiG ++JJ6l425d7JmRbNC2LFk+Hbb9G/eWZZbiZjcPQIDAQABAoIBAQDDpyxGLC/XAlNc +aYsFWMx6JcjMeM4X+yxQWYW1IMTYAYEDBNCn8BRcKGY8r1b/frNhIMmlvpLeSdSd +tL70ZGDeGRRJbBlkz9Q2QZKbm35ABhmA/jNqC/ni0mmrHY1SVmx4CnL1WCXWAmr8 +cU99JHIVI7jdoSzXrBo6GDUNbJsTI4kLmJO31zTnO3A10r6eTG6+t0kqdprcG3oE +pTpJnycy+z5cXf/8gv+yMicDpSzts0YjeSFvG0TPNVrvINsoXK837M0DycotUsik +0I1TyWMR66b8ceP34A86eWPjVQw/jU0kdDD0AN4Key/EymS21vGVml1vVNP3ZvkH +A6pE9scRAoGBAPmwb6VfRtJRPIieexqatilO6hH5B+A05FvopGdFEs7aDdnsBKXS +FalEp0ArR0DRu65c4nF0NNBUkciq5VrEdoNyz5OKIV6ypl+FOtoDpaDlgQEGctE/ +fjjw4EAt0uvCJYMjrSpeiS6aIHb9QPU5kTEjfJrIvkorRxGa4XQzvcBPAoGBAOdX +EZEEZP9Qy0GE60j12VQ9jkVrmCfWyDd1qR09iN0fXFcTr1mj5E+nQimI+3OX1ymg +EgPOqTxxGj7W9erEEpT2xlERuBVP9CnBQPjl4llTJtMNpYsX76OLCRe9QYvCkVsE +1rvCu9Kdbrok/GZIyZxPShMsxg0SnFsEKvpu2AuzAoGBAPCuv2AUcEspnYU/5wBl +I7S76et7NrlLothpb5hQP+n+zR1EYdKJqPGqSOIVFbEIurY/uNOOJZ6v9nsNKNqO +yIK6+BaLLtF+udsXrPwcSdrHf8vCMIk9f+lZX4Dd6xPw6IH5sOFHkUrHrQWl56i6 +XheU0nbNjIgoIXB58Fs3yPAHAoGAGYdCKP6TJpmD1HcWf7ahhOpGCOMWp07MSVJy +lwdzUvNi/Tju4LV1PFT4uBylotveonlHg6QKiODyRHz0JjP82PNibw/FgJSSHQl2 +YgD8OV8zqZaX7gF2MFXnavc3hHS0FZczGwUiNNuqnF/4elEN7nHResw2Drs/Bcwv +8fLJZIECgYEA17uHOALkj6m9oFeepMddgVzfTtEzhjwJIB3/dhv9K5Y6UkxOrwvE +d813gvlXziZ6StMMbbwW+TPU87Z8B92y2rMP/e3ui4Z3/ObMfeSCWX6892M3jfAu +RB4FLpR4us5RWZ7rpSyZzmA4/4NaBMxz8b6fD8vImjbbwYfJbq7oKFI= +-----END RSA PRIVATE KEY----- diff --git a/ssl/ssl.conf b/ssl/ssl.conf new file mode 100644 index 00000000..ff411a96 --- /dev/null +++ b/ssl/ssl.conf @@ -0,0 +1,39 @@ +server { + listen 443 ssl http2; + listen [::]:443 ssl http2; + + ssl_certificate /etc/ssl/dev.cac.atat.codes.crt; + ssl_certificate_key /etc/ssl/dev.cac.atat.codes.key; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:50m; + ssl_session_tickets off; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"; + ssl_prefer_server_ciphers on; + + ssl_verify_client optional; + ssl_verify_depth 10; + ssl_client_certificate /etc/ssl/ca-chain.pem; + error_log /var/log/nginx/authnid.error.log debug; + + add_header Strict-Transport-Security max-age=15768000; + #ssl_stapling on; + #ssl_stapling_verify on; + + location / { + try_files $uri @app; + } + + location @app { + include uwsgi_params; + uwsgi_pass unix:///tmp/uwsgi.sock; + uwsgi_param HTTP_X_SSL_CLIENT_VERIFY $ssl_client_verify; + uwsgi_param HTTP_X_SSL_CLIENT_CERT $ssl_client_raw_cert; + uwsgi_param HTTP_X_SSL_CLIENT_S_DN $ssl_client_s_dn; + } + + location /static { + alias /app/static; + } +} diff --git a/scss/README.md b/styles/README.md similarity index 100% rename from scss/README.md rename to styles/README.md diff --git a/scss/atat.scss b/styles/atat.scss similarity index 94% rename from scss/atat.scss rename to styles/atat.scss index b4ae7797..ad650bbd 100644 --- a/scss/atat.scss +++ b/styles/atat.scss @@ -1,5 +1,5 @@ @import 'core/variables'; -@import '../node_modules/uswds/src/stylesheets/uswds'; +@import 'node_modules/uswds/src/stylesheets/uswds'; @import 'core/grid'; @import 'core/util'; diff --git a/scss/components/_alerts.scss b/styles/components/_alerts.scss similarity index 100% rename from scss/components/_alerts.scss rename to styles/components/_alerts.scss diff --git a/scss/components/_empty_state.scss b/styles/components/_empty_state.scss similarity index 100% rename from scss/components/_empty_state.scss rename to styles/components/_empty_state.scss diff --git a/scss/components/_footer.scss b/styles/components/_footer.scss similarity index 100% rename from scss/components/_footer.scss rename to styles/components/_footer.scss diff --git a/scss/components/_global_layout.scss b/styles/components/_global_layout.scss similarity index 100% rename from scss/components/_global_layout.scss rename to styles/components/_global_layout.scss diff --git a/scss/components/_global_navigation.scss b/styles/components/_global_navigation.scss similarity index 100% rename from scss/components/_global_navigation.scss rename to styles/components/_global_navigation.scss diff --git a/scss/components/_modal.scss b/styles/components/_modal.scss similarity index 100% rename from scss/components/_modal.scss rename to styles/components/_modal.scss diff --git a/scss/components/_progress_menu.scss b/styles/components/_progress_menu.scss similarity index 96% rename from scss/components/_progress_menu.scss rename to styles/components/_progress_menu.scss index 3ca7bb72..a675dfb7 100644 --- a/scss/components/_progress_menu.scss +++ b/styles/components/_progress_menu.scss @@ -88,7 +88,7 @@ } &--complete:before { - content: url('/static/icons/checkmark.svg'); + content: url('#{$asset-path}/icons/checkmark.svg'); background-color: $color-blue; border: 2px solid $color-blue; font-size: $h6-font-size; @@ -100,4 +100,4 @@ } } -} \ No newline at end of file +} diff --git a/scss/components/_search_bar.scss b/styles/components/_search_bar.scss similarity index 95% rename from scss/components/_search_bar.scss rename to styles/components/_search_bar.scss index f5c031f8..dbc795d2 100644 --- a/scss/components/_search_bar.scss +++ b/styles/components/_search_bar.scss @@ -62,7 +62,7 @@ text-align: center; &:after { - content: url('/static/icons/search.svg'); + content: url('#{$asset-path}/icons/search.svg'); display: inline-block; width: 1.6rem; height: 1.6rem; diff --git a/scss/components/_site_action.scss b/styles/components/_site_action.scss similarity index 100% rename from scss/components/_site_action.scss rename to styles/components/_site_action.scss diff --git a/scss/components/_topbar.scss b/styles/components/_topbar.scss similarity index 100% rename from scss/components/_topbar.scss rename to styles/components/_topbar.scss diff --git a/scss/components/_workspace_layout.scss b/styles/components/_workspace_layout.scss similarity index 100% rename from scss/components/_workspace_layout.scss rename to styles/components/_workspace_layout.scss diff --git a/scss/core/_grid.scss b/styles/core/_grid.scss similarity index 100% rename from scss/core/_grid.scss rename to styles/core/_grid.scss diff --git a/scss/core/_util.scss b/styles/core/_util.scss similarity index 100% rename from scss/core/_util.scss rename to styles/core/_util.scss diff --git a/scss/core/_variables.scss b/styles/core/_variables.scss similarity index 99% rename from scss/core/_variables.scss rename to styles/core/_variables.scss index 79c0e759..19945881 100644 --- a/scss/core/_variables.scss +++ b/styles/core/_variables.scss @@ -129,7 +129,7 @@ $grid-columns-large: 12; // $large: new-breakpoint(min-width $large-screen $grid-columns-large); // Set the base path for assets (used for font and image paths below) -$asset-path: '../'; +$asset-path: '../static/'; // Relative font and image file paths $font-path: '#{$asset-path}fonts'; diff --git a/scss/elements/_action_group.scss b/styles/elements/_action_group.scss similarity index 100% rename from scss/elements/_action_group.scss rename to styles/elements/_action_group.scss diff --git a/scss/elements/_block_lists.scss b/styles/elements/_block_lists.scss similarity index 100% rename from scss/elements/_block_lists.scss rename to styles/elements/_block_lists.scss diff --git a/scss/elements/_buttons.scss b/styles/elements/_buttons.scss similarity index 100% rename from scss/elements/_buttons.scss rename to styles/elements/_buttons.scss diff --git a/scss/elements/_diff.scss b/styles/elements/_diff.scss similarity index 100% rename from scss/elements/_diff.scss rename to styles/elements/_diff.scss diff --git a/scss/elements/_icon_link.scss b/styles/elements/_icon_link.scss similarity index 100% rename from scss/elements/_icon_link.scss rename to styles/elements/_icon_link.scss diff --git a/scss/elements/_icons.scss b/styles/elements/_icons.scss similarity index 100% rename from scss/elements/_icons.scss rename to styles/elements/_icons.scss diff --git a/scss/elements/_inputs.scss b/styles/elements/_inputs.scss similarity index 100% rename from scss/elements/_inputs.scss rename to styles/elements/_inputs.scss diff --git a/scss/elements/_labels.scss b/styles/elements/_labels.scss similarity index 100% rename from scss/elements/_labels.scss rename to styles/elements/_labels.scss diff --git a/scss/elements/_panels.scss b/styles/elements/_panels.scss similarity index 100% rename from scss/elements/_panels.scss rename to styles/elements/_panels.scss diff --git a/scss/elements/_sidenav.scss b/styles/elements/_sidenav.scss similarity index 100% rename from scss/elements/_sidenav.scss rename to styles/elements/_sidenav.scss diff --git a/scss/elements/_tables.scss b/styles/elements/_tables.scss similarity index 100% rename from scss/elements/_tables.scss rename to styles/elements/_tables.scss diff --git a/scss/elements/_typography.scss b/styles/elements/_typography.scss similarity index 100% rename from scss/elements/_typography.scss rename to styles/elements/_typography.scss diff --git a/scss/sections/_login.scss b/styles/sections/_login.scss similarity index 100% rename from scss/sections/_login.scss rename to styles/sections/_login.scss diff --git a/scss/sections/_member_edit.scss b/styles/sections/_member_edit.scss similarity index 100% rename from scss/sections/_member_edit.scss rename to styles/sections/_member_edit.scss diff --git a/scss/sections/_project_edit.scss b/styles/sections/_project_edit.scss similarity index 100% rename from scss/sections/_project_edit.scss rename to styles/sections/_project_edit.scss diff --git a/scss/sections/_projects_list.scss b/styles/sections/_projects_list.scss similarity index 100% rename from scss/sections/_projects_list.scss rename to styles/sections/_projects_list.scss diff --git a/scss/sections/_request_approval.scss b/styles/sections/_request_approval.scss similarity index 100% rename from scss/sections/_request_approval.scss rename to styles/sections/_request_approval.scss diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 00000000..93dbe8e7 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,41 @@ +{# TODO: set this context elsewhere #} +{# set context='workspace' #} +{% set context=g.navigationContext %} + + + + + + + {% block title %}JEDI{% endblock %} + {% assets "css" %} + + {% endassets %} + + + + + {% block template_vars %}{% endblock %} + + {% include 'navigation/topbar.html' %} + +
+ {% include 'navigation/global_navigation.html' %} + +
+ {% block sidenav %}{% endblock %} + + {% block content %} + these are not the droids you are looking for + {% endblock %} +
+
+ + {% include 'footer.html' %} + + {% block modal %}{% endblock %} + {% assets "js_all" %} + + {% endassets %} + + diff --git a/templates/base.html.to b/templates/base.html.to deleted file mode 100644 index 3f0d5995..00000000 --- a/templates/base.html.to +++ /dev/null @@ -1,40 +0,0 @@ -{# TODO: set this context elsewhere #} -{# set context='workspace' #} -{% set context=navigationContext() %} - - - - - - - {% block title %}JEDI{% end %} - {% for url in assets['css'].urls() %} - - {% end %} - - - - - {% block template_vars %}{% end %} - - {% include 'navigation/topbar.html.to' %} - -
- {% include 'navigation/global_navigation.html.to' %} - -
- {% block sidenav %}{% end %} - - {% block content %} - these are not the droids you are looking for - {% end %} -
-
- - {% include 'footer.html.to' %} - - {% block modal %}{% end %} - - - - diff --git a/templates/base_workspace.html.to b/templates/base_workspace.html similarity index 50% rename from templates/base_workspace.html.to rename to templates/base_workspace.html index 7803ace8..fedc3278 100644 --- a/templates/base_workspace.html.to +++ b/templates/base_workspace.html @@ -1,15 +1,15 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %}
- {% include 'navigation/workspace_navigation.html.to' %} + {% include 'navigation/workspace_navigation.html' %}
- {% block workspace_content %}{% end %} + {% block workspace_content %}{% endblock %}
-{% end %} +{% endblock %} diff --git a/templates/calculator.html.to b/templates/calculator.html similarity index 69% rename from templates/calculator.html.to rename to templates/calculator.html index bf19f0a5..4f1c9a3d 100644 --- a/templates/calculator.html.to +++ b/templates/calculator.html @@ -1,4 +1,4 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %} @@ -8,5 +8,5 @@ -{% end %} +{% endblock %} diff --git a/templates/components/alert.html b/templates/components/alert.html new file mode 100644 index 00000000..d3385d1d --- /dev/null +++ b/templates/components/alert.html @@ -0,0 +1,39 @@ +{% from "components/icon.html" import Icon %} + +{% macro Alert(title, message=None, actions=None, level='info') -%} + {% set role = 'alertdialog' if actions else 'alert' %} + {% set levels = { + 'warning': { + 'icon': 'alert', + 'tone': 'assertive' + }, + 'error': { + 'icon': 'alert', + 'tone': 'assertive' + }, + 'info': { + 'icon': 'info', + 'tone': 'polite' + }, + 'success': { + 'icon': 'ok', + 'tone': 'polite' + } + } %} + +
+ {{ Icon(levels.get(level).get('icon'), classes='alert__icon icon--large') }} + +
+

{{title}}

+ + {% if message %} +
{{ message | safe }}
+ {% endif %} + + {% if actions %} +
{{ actions | safe }}
+ {% endif %} +
+
+{%- endmacro %} diff --git a/templates/components/alert.html.to b/templates/components/alert.html.to deleted file mode 100644 index 05cac613..00000000 --- a/templates/components/alert.html.to +++ /dev/null @@ -1,35 +0,0 @@ -{% set role = 'alertdialog' if actions else 'alert' %} -{% set levels = { - 'warning': { - 'icon': 'alert', - 'tone': 'assertive' - }, - 'error': { - 'icon': 'alert', - 'tone': 'assertive' - }, - 'info': { - 'icon': 'info', - 'tone': 'polite' - }, - 'success': { - 'icon': 'ok', - 'tone': 'polite' - } -} %} - -
- {% module Icon(levels.get(level).get('icon'), classes='alert__icon icon--large') %} - -
-

{{title}}

- - {% if message %} -
{% raw message %}
- {% end %} - - {% if actions %} -
{% raw actions %}
- {% end %} -
-
diff --git a/templates/components/empty_state.html b/templates/components/empty_state.html new file mode 100644 index 00000000..7dc6f119 --- /dev/null +++ b/templates/components/empty_state.html @@ -0,0 +1,13 @@ +{% from "components/icon.html" import Icon %} + +{% macro EmptyState(message, actionLabel, actionHref, icon=None) -%} +
+

{{ message }}

+ + {% if icon %} + {{ Icon(icon) }} + {% endif %} + + {{ actionLabel }} +
+{%- endmacro %} diff --git a/templates/components/empty_state.html.to b/templates/components/empty_state.html.to deleted file mode 100644 index 30246ddb..00000000 --- a/templates/components/empty_state.html.to +++ /dev/null @@ -1,9 +0,0 @@ -
-

{{ message }}

- - {% if icon %} - {% module Icon(icon) %} - {% end %} - - {{ actionLabel }} -
diff --git a/templates/components/icon.html b/templates/components/icon.html new file mode 100644 index 00000000..42139e57 --- /dev/null +++ b/templates/components/icon.html @@ -0,0 +1,6 @@ +{% macro Icon(name, classes="") -%} + {% autoescape false %} + + {% endautoescape %} +{%- endmacro %} + diff --git a/templates/components/icon.html.to b/templates/components/icon.html.to deleted file mode 100644 index 99e74b40..00000000 --- a/templates/components/icon.html.to +++ /dev/null @@ -1,2 +0,0 @@ -{% autoescape None %} - diff --git a/templates/components/modal.html b/templates/components/modal.html new file mode 100644 index 00000000..8e483de4 --- /dev/null +++ b/templates/components/modal.html @@ -0,0 +1,9 @@ +{% macro Modal() -%} + +{%- endmacro %} diff --git a/templates/components/modal.html.to b/templates/components/modal.html.to deleted file mode 100644 index 4330adbd..00000000 --- a/templates/components/modal.html.to +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/templates/components/options_input.html b/templates/components/options_input.html new file mode 100644 index 00000000..ff0d8814 --- /dev/null +++ b/templates/components/options_input.html @@ -0,0 +1,29 @@ +{% from "components/icon.html" import Icon %} + +{% macro OptionsInput(field, inline=False) -%} +
+ +
+ + {{ field.label }} + + {% if field.description %} + {{ field.description | safe }} + {% endif %} + + {% if field.errors %} + {{ Icon('alert') }} + {% endif %} + + + {{ field() }} + + {% if field.errors %} + {% for error in field.errors %} + {{ error }} + {% endfor %} + {% endif %} + +
+
+{%- endmacro %} diff --git a/templates/components/options_input.html.to b/templates/components/options_input.html.to deleted file mode 100644 index 8a15e041..00000000 --- a/templates/components/options_input.html.to +++ /dev/null @@ -1,25 +0,0 @@ -
- -
- - {{ label }} - - {% if description %} - {% raw description %} - {% end %} - - {% if errors %} - {% module Icon('alert') %} - {% end %} - - - {% raw field() %} - - {% if errors %} - {% for error in errors %} - {{ error }} - {% end %} - {% end %} - -
-
diff --git a/templates/components/sidenav_item.html b/templates/components/sidenav_item.html new file mode 100644 index 00000000..64f5b765 --- /dev/null +++ b/templates/components/sidenav_item.html @@ -0,0 +1,28 @@ +{% from "components/icon.html" import Icon %} + +{% macro SidenavItem(label, href, active=False, icon=None, subnav=None) -%} +
  • + + {% if icon %} + {{ Icon(icon, classes="sidenav__link-icon") }} + {% endif %} + + {{label}} + + + {% if subnav and active %} + + {% endif %} +
  • +{%- endmacro %} diff --git a/templates/components/text_input.html b/templates/components/text_input.html new file mode 100644 index 00000000..0f50ca89 --- /dev/null +++ b/templates/components/text_input.html @@ -0,0 +1,23 @@ +{% macro TextInput(field, placeholder='') -%} +
    + + + {{ field(placeholder=placeholder) | safe }} + + {% if field.errors %} + {% for error in field.errors %} + {{ error }} + {% endfor %} + {% endif %} +
    +{%- endmacro %} diff --git a/templates/components/text_input.html.to b/templates/components/text_input.html.to deleted file mode 100644 index 2a800abc..00000000 --- a/templates/components/text_input.html.to +++ /dev/null @@ -1,21 +0,0 @@ -
    - - - {% raw field(placeholder=placeholder) %} - - {% if errors %} - {% for error in errors %} - {{ error }} - {% end %} - {% end %} -
    diff --git a/templates/error_base.html b/templates/error_base.html new file mode 100644 index 00000000..a9d8c0de --- /dev/null +++ b/templates/error_base.html @@ -0,0 +1,38 @@ +{# TODO: set this context elsewhere #} +{# set context='workspace' #} +{% set context=g.navigationContext %} + + + + + + + {% block title %}JEDI{% endblock %} + {% assets "css" %} + + {% endassets %} + + + + + {% block template_vars %}{% endblock %} + +
    + +
    + {% block sidenav %}{% endblock %} + + {% block content %} + these are not the droids you are looking for + {% endblock %} +
    +
    + + {% include 'footer.html' %} + + {% block modal %}{% endblock %} + {% assets "js_all" %} + + {% endassets %} + + diff --git a/templates/footer.html.to b/templates/footer.html similarity index 100% rename from templates/footer.html.to rename to templates/footer.html diff --git a/templates/header.html.to b/templates/header.html similarity index 100% rename from templates/header.html.to rename to templates/header.html diff --git a/templates/home.html.to b/templates/home.html similarity index 58% rename from templates/home.html.to rename to templates/home.html index eb789f28..056d62b8 100644 --- a/templates/home.html.to +++ b/templates/home.html @@ -1,14 +1,15 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %}

    Home

    +
    -{% end %} +{% endblock %} diff --git a/templates/member_edit.html.to b/templates/member_edit.html.to index 24893bf2..fbe92f35 100644 --- a/templates/member_edit.html.to +++ b/templates/member_edit.html.to @@ -1,5 +1,7 @@ {% extends "base_workspace.html.to" %} +{% from "components/alert.html" import Alert %} + {% block template_vars %} {% set is_new_member = False %} {% set member_name = "Danny Knight" %} @@ -10,46 +12,46 @@ {% block workspace_content %} -{% module Alert( +{{ Alert( "UI Mock", message="

    Please note, this screen is a non-functional UI mockup.

    ", level="info" - ) %} + ) +}} -
    -
    -

    {{ member_name }}

    -
    Workspace Role
    {{member_workspace_role}}
    -
    -
    -
    -
    -
    DOD ID:
    -
    {{ member_id }}
    -
    -
    -
    Email:
    -
    {{ member_email }}
    -
    -
    - edit account details + +
    +
    +

    + {% if is_new_member %} + Add new member + {% else %} + {{ member_name }} + {% end %} +

    +
    Workspace Role {{member_workspace_role}}
    -
    -{% end %} +{% endblock %} diff --git a/templates/requests/menu.html b/templates/requests/menu.html new file mode 100644 index 00000000..24b28d4f --- /dev/null +++ b/templates/requests/menu.html @@ -0,0 +1,13 @@ +
    + +
    diff --git a/templates/requests/menu.html.to b/templates/requests/menu.html.to deleted file mode 100644 index 4bc77431..00000000 --- a/templates/requests/menu.html.to +++ /dev/null @@ -1,13 +0,0 @@ -
    - -
    \ No newline at end of file diff --git a/templates/requests/screen-0.html b/templates/requests/screen-0.html new file mode 100644 index 00000000..19f57d2e --- /dev/null +++ b/templates/requests/screen-0.html @@ -0,0 +1,12 @@ +{% extends '../requests_new.html.to' %} + +{% block form %} +

    New JEDI Request

    + +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus error omnis a, tenetur similique quo officiis voluptates eum recusandae dolorem minus dignissimos, magni consequatur, maxime debitis reprehenderit sint non iusto?

    + +New Application +Existing Application +Sandbox Environment + +{% endblock %} diff --git a/templates/requests/screen-0.html.to b/templates/requests/screen-0.html.to deleted file mode 100644 index 6fe78374..00000000 --- a/templates/requests/screen-0.html.to +++ /dev/null @@ -1,12 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block form %} -

    New JEDI Request

    - -

    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Natus error omnis a, tenetur similique quo officiis voluptates eum recusandae dolorem minus dignissimos, magni consequatur, maxime debitis reprehenderit sint non iusto?

    - -New Application -Existing Application -Sandbox Environment - -{% end %} diff --git a/templates/requests/screen-1.html b/templates/requests/screen-1.html new file mode 100644 index 00000000..7dbfb367 --- /dev/null +++ b/templates/requests/screen-1.html @@ -0,0 +1,48 @@ +{% extends 'requests_new.html' %} + +{% from "components/alert.html" import Alert %} +{% from "components/text_input.html" import TextInput %} +{% from "components/options_input.html" import OptionsInput %} + +{% block subtitle %} +

    Details of Use

    +{% endblock %} + +{% block form %} + +{% if f.errors %} + {{ Alert('There were some errors', + message="

    Please see below.

    ", + level='error' + ) }} +{% endif %} + + +

    We’d like to know a little about how you plan to use JEDI Cloud services to process your request. Please answer the following questions to the best of your ability. Note that the CCPO does not directly help with migrating systems to JEDI Cloud. These questions are for learning about your cloud readiness and financial usage of the JEDI Cloud; your estimates will not be used for any department level reporting.

    +

    All fields are required, unless specified optional.

    + +

    General

    +{{ TextInput(f.dod_component) }} +{{ TextInput(f.jedi_usage,placeholder="e.g. We are migrating XYZ application to the cloud so that...") }} + +

    Cloud Readiness

    +{{ TextInput(f.num_software_systems,placeholder="Number of systems") }} +{{ OptionsInput(f.jedi_migration) }} +{{ OptionsInput(f.rationalization_software_systems) }} +{{ OptionsInput(f.technical_support_team) }} +{{ OptionsInput(f.organization_providing_assistance) }} +{{ OptionsInput(f.engineering_assessment) }} +{{ TextInput(f.data_transfers) }} +{{ TextInput(f.expected_completion_date) }} +{{ OptionsInput(f.cloud_native) }} + +

    Financial Usage

    +{{ TextInput(f.estimated_monthly_spend) }} +

    So this means you are spending approximately $X annually

    +{{ TextInput(f.dollar_value) }} +{{ TextInput(f.number_user_sessions) }} +{{ TextInput(f.average_daily_traffic) }} +{{ TextInput(f.start_date) }} + + +{% endblock %} diff --git a/templates/requests/screen-1.html.to b/templates/requests/screen-1.html.to deleted file mode 100644 index a8ed7887..00000000 --- a/templates/requests/screen-1.html.to +++ /dev/null @@ -1,45 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block subtitle %} -

    Details of Use

    -{% end %} - -{% block form %} - -{% autoescape None %} -{% if f.errors %} - {% module Alert('There were some errors', - message="

    Please see below.

    ", - level='error' - ) %} -{% end %} - - -

    We’d like to know a little about how you plan to use JEDI Cloud services to process your request. Please answer the following questions to the best of your ability. Note that the CCPO does not directly help with migrating systems to JEDI Cloud. These questions are for learning about your cloud readiness and financial usage of the JEDI Cloud; your estimates will not be used for any department level reporting.

    -

    All fields are required, unless specified optional.

    - -

    General

    -{% module TextInput(f.dod_component) %} -{% module TextInput(f.jedi_usage,placeholder="e.g. We are migrating XYZ application to the cloud so that...") %} - -

    Cloud Readiness

    -{% module TextInput(f.num_software_systems,placeholder="Number of systems") %} -{% module OptionsInput(f.jedi_migration) %} -{% module OptionsInput(f.rationalization_software_systems) %} -{% module OptionsInput(f.technical_support_team) %} -{% module OptionsInput(f.organization_providing_assistance) %} -{% module OptionsInput(f.engineering_assessment) %} -{% module TextInput(f.data_transfers) %} -{% module TextInput(f.expected_completion_date) %} -{% module OptionsInput(f.cloud_native) %} - -

    Financial Usage

    -{% module TextInput(f.estimated_monthly_spend) %} -

    So this means you are spending approximately $X annually

    -{% module TextInput(f.dollar_value) %} -{% module TextInput(f.number_user_sessions) %} -{% module TextInput(f.average_daily_traffic) %} -{% module TextInput(f.start_date) %} - - -{% end %} diff --git a/templates/requests/screen-2.html b/templates/requests/screen-2.html new file mode 100644 index 00000000..be32dc90 --- /dev/null +++ b/templates/requests/screen-2.html @@ -0,0 +1,34 @@ +{% extends 'requests_new.html' %} + +{% from "components/alert.html" import Alert %} +{% from "components/text_input.html" import TextInput %} +{% from "components/options_input.html" import OptionsInput %} + +{% block subtitle %} +

    Information About You

    +{% endblock %} + +{% block form %} + +{% if f.errors %} + {{ Alert('There were some errors', + message="

    Please see below.

    ", + level='error' + ) }} +{% endif %} + +

    Please tell us more about you.

    + +{{ TextInput(f.fname_request,placeholder='First Name') }} +{{ TextInput(f.lname_request,placeholder='Last Name') }} +{{ TextInput(f.email_request,placeholder='jane@mail.mil') }} +{{ TextInput(f.phone_number,placeholder='(123) 456-7890') }} + +

    We want to collect the following information from you for security auditing and determining priviledged user access

    + +{{ TextInput(f.service_branch,placeholder='e.g. US Air Force, US Army, US Navy, Marine Corps, Defense Media Agency') }} +{{ OptionsInput(f.citizenship) }} +{{ OptionsInput(f.designation) }} +{{ TextInput(f.date_latest_training) }} + +{% endblock %} diff --git a/templates/requests/screen-2.html.to b/templates/requests/screen-2.html.to deleted file mode 100644 index fb667dc5..00000000 --- a/templates/requests/screen-2.html.to +++ /dev/null @@ -1,31 +0,0 @@ -{% extends '../requests_new.html.to' %} - -{% block subtitle %} -

    Information About You

    -{% end %} - -{% block form %} - -{% autoescape None %} -{% if f.errors %} - {% module Alert('There were some errors', - message="

    Please see below.

    ", - level='error' - ) %} -{% end %} - -

    Please tell us more about you.

    - -{% module TextInput(f.fname_request,placeholder='First Name') %} -{% module TextInput(f.lname_request,placeholder='Last Name') %} -{% module TextInput(f.email_request,placeholder='jane@mail.mil') %} -{% module TextInput(f.phone_number,placeholder='(123) 456-7890') %} - -

    We want to collect the following information from you for security auditing and determining priviledged user access

    - -{% module TextInput(f.service_branch,placeholder='e.g. US Air Force, US Army, US Navy, Marine Corps, Defense Media Agency') %} -{% module OptionsInput(f.citizenship) %} -{% module OptionsInput(f.designation) %} -{% module TextInput(f.date_latest_training) %} - -{% end %} \ No newline at end of file diff --git a/templates/requests/screen-3.html.to b/templates/requests/screen-3.html similarity index 66% rename from templates/requests/screen-3.html.to rename to templates/requests/screen-3.html index af4ea66f..7de95813 100644 --- a/templates/requests/screen-3.html.to +++ b/templates/requests/screen-3.html @@ -1,18 +1,20 @@ -{% extends '../requests_new.html.to' %} +{% extends 'requests_new.html' %} + +{% from "components/alert.html" import Alert %} +{% from "components/text_input.html" import TextInput %} {% block subtitle %}

    Primary Government/Military
    Point of Contact (POC)

    -{% end %} +{% endblock %} {% block form %} -{% autoescape None %} {% if f.errors %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please see below.

    ", level='error' - ) %} -{% end %} + ) }} +{% endif %}

    Please designate a Primary Point of Contact that will be responsible for owning the workspace in the JEDI Cloud.

    The Point of Contact will become the primary owner of the workspace created to use the JEDI Cloud. As a workspace owner, this person will have the ability to: @@ -26,9 +28,9 @@ This POC may be you.

    -{% module TextInput(f.fname_poc,placeholder='First Name') %} -{% module TextInput(f.lname_poc,placeholder='Last Name') %} -{% module TextInput(f.email_poc,placeholder='jane@mail.mil') %} -{% module TextInput(f.dodid_poc,placeholder='10-digit number on the back of the CAC') %} +{{ TextInput(f.fname_poc,placeholder='First Name') }} +{{ TextInput(f.lname_poc,placeholder='Last Name') }} +{{ TextInput(f.email_poc,placeholder='jane@mail.mil') }} +{{ TextInput(f.dodid_poc,placeholder='10-digit number on the back of the CAC') }} -{% end %} \ No newline at end of file +{% endblock %} diff --git a/templates/requests/screen-4.html.to b/templates/requests/screen-4.html similarity index 82% rename from templates/requests/screen-4.html.to rename to templates/requests/screen-4.html index 60dd06ac..2e940e57 100644 --- a/templates/requests/screen-4.html.to +++ b/templates/requests/screen-4.html @@ -1,27 +1,29 @@ -{% extends '../requests_new.html.to' %} +{% extends 'requests_new.html' %} + +{% from "components/alert.html" import Alert %} +{% from "components/text_input.html" import TextInput %} {% block subtitle %}

    Review & Submit

    -{% end %} +{% endblock %} {% block form_action %} -
    - {% end %} + +{% endblock %} {% block form %} - {% autoescape None %} {% if f.errors %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please complete all required fields before submitting.

    ", level='error' - ) %} - {% end %} + ) }} + {% endif %}

    Before you can submit your request, please take a moment to review the information entered in the form. You may make changes by clicking the edit link on each section. When all information looks right, go ahead and submit.

    -

    Details of Use Edit

    +

    Details of Use Edit

    @@ -107,7 +109,7 @@
    -

    Information About You Edit

    +

    Information About You Edit

    @@ -152,7 +154,7 @@
    -

    Primary Point of Contact Edit

    +

    Primary Point of Contact Edit

    @@ -178,15 +180,15 @@ -{% end %} +{% endblock %} {% block next %} {% if not can_submit %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please complete all required fields before submitting.

    ", level='error' - ) %} -{% end %} + ) }} +{% endif %}
    @@ -194,4 +196,4 @@ -{% end %} +{% endblock %} diff --git a/templates/requests/screen-5.html.to b/templates/requests/screen-5.html similarity index 91% rename from templates/requests/screen-5.html.to rename to templates/requests/screen-5.html index e8642f1e..9c5b16ac 100644 --- a/templates/requests/screen-5.html.to +++ b/templates/requests/screen-5.html @@ -1,14 +1,15 @@ {% extends '../requests_new.html.to' %} +{% from "components/alert.html" import Alert %} + {% block form %} -{% autoescape None %} {% if f.errors %} - {% module Alert('There were some errors', + {{ Alert('There were some errors', message="

    Please complete all the fields before submitting.

    ", level='error' - ) %} -{% end %} + ) }} +{% endif %}

    Financial Verification

    @@ -20,7 +21,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.uii_ids.label }} {{ f.uii_ids(placeholder="Example: \nDI 0CVA5786950 \nUN1945326361234786950") }} @@ -28,7 +29,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.pe_id.label }} {{ f.pe_id(placeholder="Example: 0203752A") }} @@ -36,7 +37,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.treasury_code.label }} {{ f.treasury_code(placeholder="Example: 1200") }} @@ -44,7 +45,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.ba_code.label }} {{ f.ba_code(placeholder="Example: 02") }} @@ -52,7 +53,7 @@
    {{ e }}
    -{% end %} +{% endfor %} @@ -64,7 +65,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.lname_co.label }} {{ f.lname_co(placeholder="Contracting Officer last name") }} @@ -72,7 +73,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.email_co.label }} {{ f.email_co(placeholder="jane@mail.mil") }} @@ -80,7 +81,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.office_co.label }} {{ f.office_co(placeholder="Example: WHS") }} @@ -88,7 +89,7 @@
    {{ e }}
    -{% end %} +{% endfor %} @@ -101,7 +102,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.lname_cor.label }} {{ f.lname_cor(placeholder="Contracting Officer Representative last name") }} @@ -109,7 +110,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.email_cor.label }} {{ f.email_cor(placeholder="jane@mail.mil") }} @@ -117,7 +118,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.office_cor.label }} {{ f.office_cor(placeholder="Example: WHS") }} @@ -125,7 +126,7 @@
    {{ e }}
    -{% end %} +{% endfor %}

    ↓ FIELDS NEEDED FOR MANUAL ENTRY OF TASK ORDER INFORMATION (only necessary if EDA info not available) @@ -137,7 +138,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.funding_type_other.label }} {{ f.funding_type_other(placeholder="") }} @@ -145,7 +146,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_0001.label }} {{ f.clin_0001(placeholder="50,000") }} @@ -153,7 +154,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_0003.label }} {{ f.clin_0003(placeholder="13,000") }} @@ -161,7 +162,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_1001.label }} {{ f.clin_1001(placeholder="30,000") }} @@ -169,7 +170,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_1003.label }} {{ f.clin_1003(placeholder="7,000") }} @@ -177,7 +178,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_2001.label }} {{ f.clin_2001(placeholder="30,000") }} @@ -185,7 +186,7 @@
    {{ e }}
    -{% end %} +{% endfor %} {{ f.clin_2003.label }} {{ f.clin_2003(placeholder="7,000") }} @@ -193,7 +194,7 @@
    {{ e }}
    -{% end %} +{% endfor %} -{% end %} +{% endblock %} diff --git a/templates/requests/sidebar.html.to b/templates/requests/sidebar.html similarity index 100% rename from templates/requests/sidebar.html.to rename to templates/requests/sidebar.html diff --git a/templates/requests_new.html b/templates/requests_new.html new file mode 100644 index 00000000..559c2355 --- /dev/null +++ b/templates/requests_new.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} + +{% block content %} + +
    + + {% include 'requests/menu.html' %} + +
    + +
    +

    New Request

    +
    {% block subtitle %}{% endblock %}
    +
    + +
    + {% block form_action %} + {% if request_id %} +
    + {% else %} + + {% endif %} + {% endblock %} + + {{ f.csrf_token }} + {% block form %} + form goes here + {% endblock %} + +
    + +
    + + {% block next %} + +
    + +
    + + {% endblock %} + + +
    + +{% endblock %} diff --git a/templates/requests_new.html.to b/templates/requests_new.html.to deleted file mode 100644 index 5a309f26..00000000 --- a/templates/requests_new.html.to +++ /dev/null @@ -1,46 +0,0 @@ -{% extends "base.html.to" %} - -{% block content %} - -
    - - {% include 'requests/menu.html.to' %} - -
    - -
    -

    New Request

    -
    {% block subtitle %}{% end %}
    -
    - -
    - {% block form_action %} - {% if request_id %} -
    - {% else %} - - {% end %} - {% end %} - - {% module xsrf_form_html() %} - {% block form %} - form goes here - {% end %} - -
    - -
    - - {% block next %} - -
    - -
    - - {% end %} - - -
    - -{% end %} - diff --git a/templates/root.html.to b/templates/root.html similarity index 63% rename from templates/root.html.to rename to templates/root.html index 40bef97e..090196ec 100644 --- a/templates/root.html.to +++ b/templates/root.html @@ -3,10 +3,10 @@ - {% block title %}JEDI{% end %} - {% for url in assets['css'].urls() %} - - {% end %} + {% block title %}JEDI{% endblock %} + {% assets "css" %} + + {% endassets %} @@ -17,11 +17,11 @@

    JEDI

    - Sign In with CAC + Sign In with CAC - {% if dev() %} + {% if g.dev %} DEV Login - {% end %} + {% endif %} diff --git a/templates/styleguide.html.to b/templates/styleguide.html similarity index 82% rename from templates/styleguide.html.to rename to templates/styleguide.html index 1db19496..14eaf96e 100644 --- a/templates/styleguide.html.to +++ b/templates/styleguide.html @@ -1,8 +1,12 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} + +{% from "components/icon.html" import Icon %} +{% from "components/modal.html" import Modal %} +{% from "components/alert.html" import Alert %} {% block modal %} - {% if modalOpen() %} - {% apply modal %} + {% if g.modalOpen %} + {% call Modal() %}

    A modal dialog

    We count thirty Rebel ships, Lord Vader. But they're so small they're evading our turbo-lasers! We'll have to destroy them ship to ship. Get the crews to their fighters. Luke, let me know when you're going in. I'm on my way in now... Watch yourself! There's a lot of fire coming from the right side of that deflection tower. I'm on it. Squad leaders, we've picked up a new group of signals. Enemy fighters coming your way.

    @@ -12,35 +16,35 @@ Close This also closes the modal
    - {% end %} - {% end %} -{% end %} + {% endcall %} + {% endif %} +{% endblock %} {% block content %} -{% module Alert('A Warning Alert', +{{ Alert('A Warning Alert', message="\

    This is a message. It is a very important message. Please note, proper semantic markup is required here, such as paragraph tags. Don't omit paragraph tags!

    \

    Also note the same for actions below. You'll need to include the full link markup.

    \ ", actions="Open a Modal Dialog", level='warning' -) %} +) }} -{% module Alert('A Success Alert', +{{ Alert('A Success Alert', message="

    Congratulations! You did a thing.

    ", level='success' -) %} +) }} -{% module Alert('An Error Alert', +{{ Alert('An Error Alert', message="

    Booooo. You're the worst.

    ", level='error' -) %} +) }} -{% module Alert('An Info Alert', +{{ Alert('An Info Alert', message="

    The more you know.

    " -) %} +) }}
    @@ -214,7 +218,7 @@
    - Inline Checkboxes {% module Icon('alert') %} + Inline Checkboxes {{ Icon('alert') }} @@ -234,7 +238,7 @@
    - Problem Radio Buttons {% module Icon('alert') %} + Problem Radio Buttons {{ Icon('alert') }} @@ -279,30 +283,30 @@
    Icons
    - {% module Icon('trash') %} 'trash'    - {% module Icon('document') %} 'document'    - {% module Icon('cloud') %} 'cloud'    - {% module Icon('chart') %} 'chart'    - {% module Icon('caret_up') %} 'caret_up'    - {% module Icon('caret_down') %} 'caret_down'    - {% module Icon('caret_right') %} 'caret_right'    - {% module Icon('caret_left') %} 'caret_left'    - {% module Icon('x') %} 'x'    - {% module Icon('search') %} 'search'    - {% module Icon('avatar') %} 'avatar'    - {% module Icon('download') %} 'download'    - {% module Icon('briefcase') %} 'briefcase'    - {% module Icon('bell') %} 'bell'    - {% module Icon('folder') %} 'folder'    - {% module Icon('help') %} 'help'    - {% module Icon('shield') %} 'shield'    - {% module Icon('info') %} 'info'    - {% module Icon('alert') %} 'alert'    - {% module Icon('link') %} 'link'    - {% module Icon('ok') %} 'ok'    - {% module Icon('checkmark') %} 'checkmark'    - {% module Icon('arrow-right') %} 'arrow-right'    - {% module Icon('arrow-down') %} 'arrow-down'    + {{ Icon('trash') }} 'trash'    + {{ Icon('document') }} 'document'    + {{ Icon('cloud') }} 'cloud'    + {{ Icon('chart') }} 'chart'    + {{ Icon('caret_up') }} 'caret_up'    + {{ Icon('caret_down') }} 'caret_down'    + {{ Icon('caret_right') }} 'caret_right'    + {{ Icon('caret_left') }} 'caret_left'    + {{ Icon('x') }} 'x'    + {{ Icon('search') }} 'search'    + {{ Icon('avatar') }} 'avatar'    + {{ Icon('download') }} 'download'    + {{ Icon('briefcase') }} 'briefcase'    + {{ Icon('bell') }} 'bell'    + {{ Icon('folder') }} 'folder'    + {{ Icon('help') }} 'help'    + {{ Icon('shield') }} 'shield'    + {{ Icon('info') }} 'info'    + {{ Icon('alert') }} 'alert'    + {{ Icon('link') }} 'link'    + {{ Icon('ok') }} 'ok'    + {{ Icon('checkmark') }} 'checkmark'    + {{ Icon('arrow-right') }} 'arrow-right'    + {{ Icon('arrow-down') }} 'arrow-down'   
    @@ -360,4 +364,4 @@ Action group link
    -{% end %} +{% endblock %} diff --git a/templates/unauthorized.html b/templates/unauthorized.html new file mode 100644 index 00000000..efaa3b95 --- /dev/null +++ b/templates/unauthorized.html @@ -0,0 +1,12 @@ +{% extends "error_base.html" %} + +{% block content %} + +
    + +

    Unauthorized

    + +
    + +{% endblock %} + diff --git a/templates/users.html.to b/templates/users.html similarity index 68% rename from templates/users.html.to rename to templates/users.html index ee050f69..9d6523f7 100644 --- a/templates/users.html.to +++ b/templates/users.html @@ -1,4 +1,4 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %} @@ -8,5 +8,5 @@ -{% end %} +{% endblock %} diff --git a/templates/workspace_members.html.to b/templates/workspace_members.html similarity index 91% rename from templates/workspace_members.html.to rename to templates/workspace_members.html index 0f538b05..19cb340f 100644 --- a/templates/workspace_members.html.to +++ b/templates/workspace_members.html @@ -1,15 +1,17 @@ -{% extends "base_workspace.html.to" %} +{% extends "base_workspace.html" %} + +{% from "components/empty_state.html" import EmptyState %} {% block workspace_content %} {% if not members %} - {% module EmptyState( + {{ EmptyState( 'There are currently no members in this Workspace.', actionLabel='Invite a new Member', actionHref='/members/new', icon='avatar' - )%} + ) }} {% else %} @@ -59,17 +61,17 @@ {% for m in members %} {{ m['first_name'] }} {{ m['last_name'] }} - {% if m['num_projects'] == '0' %} No Project Access {% end %} + {% if m['num_projects'] == '0' %} No Project Access {% endif %} {{ m['status'] }} {{ m['workspace_role'] }} - {% end %} + {% endfor %}
    -{% end %} +{% endif %} -{% end %} +{% endblock %} diff --git a/templates/workspace_projects.html.to b/templates/workspace_projects.html similarity index 71% rename from templates/workspace_projects.html.to rename to templates/workspace_projects.html index a9f1a8aa..a7f51df1 100644 --- a/templates/workspace_projects.html.to +++ b/templates/workspace_projects.html @@ -1,13 +1,15 @@ -{% extends "base_workspace.html.to" %} +{% from "components/icon.html" import Icon %} + +{% extends "base_workspace.html" %} {% block workspace_content %} {% for project in projects %}
    -

    {{ project['name'] }} ({{ len(project['environments'])}} environments)

    +

    {{ project['name'] }} ({{ project['environments']|length }} environments)

    - {% module Icon('edit') %} + {{ Icon('edit') }} edit
    @@ -15,7 +17,7 @@ {% for environment in project['environments'] %}
  • - {% module Icon('link') %} + {{ Icon('link') }} {{ environment["name"]}} @@ -24,10 +26,10 @@ members
  • - {% end %} + {% endfor %}
    -{% end %} +{% endfor %} -{% end %} +{% endblock %} diff --git a/templates/workspaces.html.to b/templates/workspaces.html similarity index 91% rename from templates/workspaces.html.to rename to templates/workspaces.html index 21bbad7d..5f407766 100644 --- a/templates/workspaces.html.to +++ b/templates/workspaces.html @@ -1,4 +1,4 @@ -{% extends "base.html.to" %} +{% extends "base.html" %} {% block content %}
    @@ -23,9 +23,9 @@ {{ w['user_count'] }}Users - {% end %} + {% endfor %}
    -{% end %} +{% endblock %} diff --git a/tests/conftest.py b/tests/conftest.py index c650b5f1..bdc59286 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,25 +1,65 @@ +import os import pytest +import alembic.config +import alembic.command -from atst.app import make_app, make_deps, make_config -from tests.mocks import MockApiClient, MockFundzClient, MockRequestsClient, MockAuthzClient -from atst.sessions import DictSessions +from atst.app import make_app, make_config +from atst.database import db as _db +from .mocks import MOCK_USER -@pytest.fixture -def app(): - TEST_DEPS = { - "authz_client": MockAuthzClient("authz"), - "requests_client": MockRequestsClient("requests"), - "authnid_client": MockApiClient("authnid"), - "fundz_client": MockFundzClient("fundz"), - "sessions": DictSessions(), - } - +@pytest.fixture(scope='session') +def app(request): config = make_config() - deps = make_deps(config) - deps.update(TEST_DEPS) - return make_app(config, deps) + _app = make_app(config) + + ctx = _app.app_context() + ctx.push() + + yield _app + + ctx.pop() + + +def apply_migrations(): + """Applies all alembic migrations.""" + alembic_config = os.path.join(os.path.dirname(__file__), "../", "alembic.ini") + config = alembic.config.Config(alembic_config) + app_config = make_config() + config.set_main_option('sqlalchemy.url', app_config["DATABASE_URI"]) + alembic.command.upgrade(config, 'head') + + +@pytest.fixture(scope='session') +def db(app, request): + + _db.app = app + + apply_migrations() + + yield _db + + _db.drop_all() + + +@pytest.fixture(scope='function', autouse=True) +def session(db, request): + """Creates a new database session for a test.""" + connection = db.engine.connect() + transaction = connection.begin() + + options = dict(bind=connection, binds={}) + session = db.create_scoped_session(options=options) + + db.session = session + + yield session + + transaction.rollback() + connection.close() + session.remove() + class DummyForm(dict): pass @@ -40,3 +80,11 @@ def dummy_form(): @pytest.fixture def dummy_field(): return DummyField() + +@pytest.fixture +def user_session(monkeypatch): + + def set_user_session(user = MOCK_USER): + monkeypatch.setattr("atst.domain.auth.get_current_user", lambda *args: user) + + return set_user_session diff --git a/tests/domain/__init__.py b/tests/domain/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/domain/authnid/test_crl.py b/tests/domain/authnid/test_crl.py new file mode 100644 index 00000000..6bfdd99e --- /dev/null +++ b/tests/domain/authnid/test_crl.py @@ -0,0 +1,86 @@ +# Import installed packages +import pytest +import re +import os +import shutil +from OpenSSL import crypto, SSL +from atst.domain.authnid.crl.validator import Validator +import atst.domain.authnid.crl.util as util + + +class MockX509Store(): + def __init__(self): + self.crls = [] + self.certs = [] + + def add_crl(self, crl): + self.crls.append(crl) + + def add_cert(self, cert): + self.certs.append(cert) + + def set_flags(self, flag): + pass + +def test_can_build_crl_list(monkeypatch): + location = 'ssl/client-certs/client-ca.der.crl' + validator = Validator(crl_locations=[location], base_store=MockX509Store) + assert len(validator.store.crls) == 1 + +def test_can_build_trusted_root_list(): + location = 'ssl/server-certs/ca-chain.pem' + validator = Validator(roots=[location], base_store=MockX509Store) + with open(location) as f: + content = f.read() + assert len(validator.store.certs) == content.count('BEGIN CERT') + +def test_can_validate_certificate(): + validator = Validator( + roots=['ssl/server-certs/ca-chain.pem'], + crl_locations=['ssl/client-certs/client-ca.der.crl'] + ) + good_cert = open('ssl/client-certs/atat.mil.crt', 'rb').read() + bad_cert = open('ssl/client-certs/bad-atat.mil.crt', 'rb').read() + assert validator.validate(good_cert) + assert validator.validate(bad_cert) == False + +def test_can_dynamically_update_crls(tmpdir): + crl_file = tmpdir.join('test.crl') + shutil.copyfile('ssl/client-certs/client-ca.der.crl', crl_file) + validator = Validator( + roots=['ssl/server-certs/ca-chain.pem'], + crl_locations=[crl_file] + ) + cert = open('ssl/client-certs/atat.mil.crt', 'rb').read() + assert validator.validate(cert) + # override the original CRL with one that revokes atat.mil.crt + shutil.copyfile('tests/fixtures/test.der.crl', crl_file) + assert validator.validate(cert) == False + +def test_parse_disa_pki_list(): + with open('tests/fixtures/disa-pki.html') as disa: + disa_html = disa.read() + crl_list = util.crl_list_from_disa_html(disa_html) + href_matches = re.findall('DOD(ROOT|EMAIL|ID)?CA', disa_html) + assert len(crl_list) > 0 + assert len(crl_list) == len(href_matches) + +class MockStreamingResponse(): + def __init__(self, content_chunks): + self.content_chunks = content_chunks + + def iter_content(self, chunk_size=0): + return self.content_chunks + + def __enter__(self): + return self + + def __exit__(self, *args): + pass + +def test_write_crl(tmpdir, monkeypatch): + monkeypatch.setattr('requests.get', lambda u, **kwargs: MockStreamingResponse([b'it worked'])) + crl = 'crl_1' + util.write_crl(tmpdir, crl) + assert [p.basename for p in tmpdir.listdir()] == [crl] + assert [p.read() for p in tmpdir.listdir()] == ['it worked'] diff --git a/tests/domain/authnid/test_utils.py b/tests/domain/authnid/test_utils.py new file mode 100644 index 00000000..caaa29f9 --- /dev/null +++ b/tests/domain/authnid/test_utils.py @@ -0,0 +1,16 @@ +import pytest +import atst.domain.authnid.utils as utils +from tests.mocks import DOD_SDN + + +def test_parse_sdn(): + parsed = utils.parse_sdn(DOD_SDN) + assert parsed.get('first_name') == 'ART' + assert parsed.get('last_name') == 'GARFUNKEL' + assert parsed.get('dod_id') == '5892460358' + +def test_parse_bad_sdn(): + with pytest.raises(ValueError): + utils.parse_sdn('this has nothing to do with anything') + with pytest.raises(ValueError): + utils.parse_sdn(None) diff --git a/tests/domain/test_pe_numbers.py b/tests/domain/test_pe_numbers.py new file mode 100644 index 00000000..60c410b5 --- /dev/null +++ b/tests/domain/test_pe_numbers.py @@ -0,0 +1,37 @@ +import pytest + +from atst.domain.exceptions import NotFoundError +from atst.domain.pe_numbers import PENumbers + +from tests.factories import PENumberFactory + + +@pytest.fixture(scope="function") +def new_pe_number(session): + def make_pe_number(**kwargs): + pen = PENumberFactory.create(**kwargs) + session.add(pen) + session.commit() + + return pen + + return make_pe_number + + +def test_can_get_pe_number(new_pe_number): + new_pen = new_pe_number(number="0701367F", description="Combat Support - Offensive") + pen = PENumbers.get(new_pen.number) + + assert pen.number == new_pen.number + + +def test_nonexistent_pe_number_raises(): + with pytest.raises(NotFoundError): + PENumbers.get("some fake number") + +def test_create_many(): + pen_list = [['123456', 'Land Speeder'], ['7891011', 'Lightsaber']] + PENumbers.create_many(pen_list) + + assert PENumbers.get(pen_list[0][0]) + assert PENumbers.get(pen_list[1][0]) diff --git a/tests/domain/test_requests.py b/tests/domain/test_requests.py new file mode 100644 index 00000000..901caf73 --- /dev/null +++ b/tests/domain/test_requests.py @@ -0,0 +1,48 @@ +import pytest +from uuid import uuid4 + +from atst.domain.exceptions import NotFoundError +from atst.domain.requests import Requests + +from tests.factories import RequestFactory + + +@pytest.fixture(scope="function") +def new_request(session): + created_request = RequestFactory.create() + session.add(created_request) + session.commit() + + return created_request + + +def test_can_get_request(new_request): + request = Requests.get(new_request.id) + + assert request.id == new_request.id + + +def test_nonexistent_request_raises(): + with pytest.raises(NotFoundError): + Requests.get(uuid4()) + + +def test_auto_approve_less_than_1m(new_request): + new_request.body = {"details_of_use": {"dollar_value": 999999}} + request = Requests.submit(new_request) + + assert request.status == 'approved' + + +def test_dont_auto_approve_if_dollar_value_is_1m_or_above(new_request): + new_request.body = {"details_of_use": {"dollar_value": 1000000}} + request = Requests.submit(new_request) + + assert request.status == 'submitted' + + +def test_dont_auto_approve_if_no_dollar_value_specified(new_request): + new_request.body = {"details_of_use": {}} + request = Requests.submit(new_request) + + assert request.status == 'submitted' diff --git a/tests/domain/test_roles.py b/tests/domain/test_roles.py new file mode 100644 index 00000000..b0da57f1 --- /dev/null +++ b/tests/domain/test_roles.py @@ -0,0 +1,18 @@ +import pytest +from atst.domain.roles import Roles +from atst.domain.exceptions import NotFoundError + + +def test_get_all_roles(): + roles = Roles.get_all() + assert roles + + +def test_get_existing_role(): + role = Roles.get("developer") + assert role.name == "developer" + + +def test_get_nonexistent_role(): + with pytest.raises(NotFoundError): + Roles.get("nonexistent") diff --git a/tests/domain/test_task_orders.py b/tests/domain/test_task_orders.py new file mode 100644 index 00000000..2f03a6d0 --- /dev/null +++ b/tests/domain/test_task_orders.py @@ -0,0 +1,30 @@ +import pytest + +from atst.domain.exceptions import NotFoundError +from atst.domain.task_orders import TaskOrders + +from tests.factories import TaskOrderFactory + + +@pytest.fixture(scope="function") +def new_task_order(session): + def make_task_order(**kwargs): + to = TaskOrderFactory.create(**kwargs) + session.add(to) + session.commit() + + return to + + return make_task_order + + +def test_can_get_task_order(new_task_order): + new_to = new_task_order(number="0101969F") + to = TaskOrders.get(new_to.number) + + assert to.id == to.id + + +def test_nonexistent_task_order_raises(): + with pytest.raises(NotFoundError): + TaskOrders.get("some fake number") diff --git a/tests/domain/test_users.py b/tests/domain/test_users.py new file mode 100644 index 00000000..16d78366 --- /dev/null +++ b/tests/domain/test_users.py @@ -0,0 +1,65 @@ +import pytest +from uuid import uuid4 + +from atst.domain.users import Users +from atst.domain.exceptions import NotFoundError + +DOD_ID = "my_dod_id" + + +def test_create_user(): + user = Users.create("developer") + assert user.atat_role.name == "developer" + + +def test_create_user_with_nonexistent_role(): + with pytest.raises(NotFoundError): + Users.create("nonexistent") + + +def test_get_or_create_nonexistent_user(): + user = Users.get_or_create_by_dod_id(DOD_ID, atat_role_name="developer") + assert user.dod_id == DOD_ID + + +def test_get_or_create_existing_user(): + Users.get_or_create_by_dod_id(DOD_ID, atat_role_name="developer") + user = Users.get_or_create_by_dod_id(DOD_ID, atat_role_name="developer") + assert user + + +def test_get_user(): + new_user = Users.create("developer") + user = Users.get(new_user.id) + assert user.id == new_user.id + + +def test_get_nonexistent_user(): + Users.create("developer") + with pytest.raises(NotFoundError): + Users.get(uuid4()) + + +def test_get_user_by_dod_id(): + new_user = Users.create("developer", dod_id=DOD_ID) + user = Users.get_by_dod_id(DOD_ID) + assert user == new_user + + +def test_update_user(): + new_user = Users.create("developer") + updated_user = Users.update(new_user.id, "ccpo") + + assert updated_user.atat_role.name == "ccpo" + + +def test_update_nonexistent_user(): + Users.create("developer") + with pytest.raises(NotFoundError): + Users.update(uuid4(), "ccpo") + + +def test_update_existing_user_with_nonexistent_role(): + new_user = Users.create("developer") + with pytest.raises(NotFoundError): + Users.update(new_user.id, "nonexistent") diff --git a/tests/domain/test_workspace_users.py b/tests/domain/test_workspace_users.py new file mode 100644 index 00000000..2c651235 --- /dev/null +++ b/tests/domain/test_workspace_users.py @@ -0,0 +1,32 @@ +from uuid import uuid4 + +from atst.domain.workspace_users import WorkspaceUsers +from atst.domain.users import Users + + +def test_can_create_new_workspace_user(): + workspace_id = uuid4() + user = Users.create("developer") + + workspace_user_dicts = [{"id": user.id, "workspace_role": "owner"}] + + workspace_users = WorkspaceUsers.add_many(workspace_id, workspace_user_dicts) + + assert workspace_users[0].user.id == user.id + assert workspace_users[0].user.atat_role.name == "developer" + assert workspace_users[0].workspace_role.role.name == "owner" + + +def test_can_update_existing_workspace_user(): + workspace_id = uuid4() + user = Users.create("developer") + + WorkspaceUsers.add_many( + workspace_id, [{"id": user.id, "workspace_role": "owner"}] + ) + workspace_users = WorkspaceUsers.add_many( + workspace_id, [{"id": user.id, "workspace_role": "developer"}] + ) + + assert workspace_users[0].user.id == user.id + assert workspace_users[0].workspace_role.role.name == "developer" diff --git a/tests/factories.py b/tests/factories.py new file mode 100644 index 00000000..11b11a1b --- /dev/null +++ b/tests/factories.py @@ -0,0 +1,40 @@ +import factory +from uuid import uuid4 + +from atst.models import Request +from atst.models.pe_number import PENumber +from atst.models.task_order import TaskOrder +from atst.models.user import User +from atst.models.role import Role + + +class RequestFactory(factory.Factory): + class Meta: + model = Request + + id = factory.Sequence(lambda x: uuid4()) + +class PENumberFactory(factory.Factory): + class Meta: + model = PENumber + +class TaskOrderFactory(factory.Factory): + class Meta: + model = TaskOrder + +class RoleFactory(factory.Factory): + class Meta: + model = Role + + permissions = [] + +class UserFactory(factory.Factory): + class Meta: + model = User + + id = factory.Sequence(lambda x: uuid4()) + email = "fake.user@mail.com" + first_name = "Fake" + last_name = "User" + atat_role = factory.SubFactory(RoleFactory) + diff --git a/tests/fixtures/crl/client-ca.der.crl b/tests/fixtures/crl/client-ca.der.crl new file mode 100644 index 00000000..8ec9e37f Binary files /dev/null and b/tests/fixtures/crl/client-ca.der.crl differ diff --git a/tests/fixtures/disa-pki.html b/tests/fixtures/disa-pki.html new file mode 100644 index 00000000..9510ab9f --- /dev/null +++ b/tests/fixtures/disa-pki.html @@ -0,0 +1,75 @@ + + + + +DoD PKI CRLDPs + + + +

    UNCLASSIFIED
    + +

    This list is provided by DoD PKE Engineering. It is updated as new CAs come online.
    +This is a list of CRL Distribution Points (CRLDPs) for all DoD CAs.

    +

    Updated April 5, 2018

    + +DoD Root CA 2
    +DoD Root CA 3
    +DoD Root CA 4
    +DoD Root CA 5
    +DoD Interoperability Root CA 1
    +DoD Interoperability Root CA 2
    +NIPR INTERNAL NPE ROOT CA 1
    +DoD NPE Root CA 1
    +DoD WCF Root CA 1
    +DoD CCEB Interoperability Root CA 1
    +DoD CCEB Interoperability Root CA 2
    +DoD DMDN Signing CA 1
    +DoD CA-31
    +DoD CA-32
    +DoD ID CA-33
    +DoD ID CA-34
    +DoD ID SW CA-35
    +DoD ID SW CA-36
    +DoD ID SW CA-37
    +DoD ID SW CA-38
    +DoD ID CA-39
    +DoD ID CA-40
    +DoD ID CA-41
    +DoD ID CA-42
    +DoD ID CA-43
    +DoD ID CA-44
    +DoD ID SW CA-45
    +DoD ID SW CA-46
    +DoD ID SW CA-47
    +DoD ID SW CA-48
    +DoD ID CA-49
    +DoD ID CA-50
    +DoD ID CA-51
    +DoD ID CA-52
    +DoD EMAIL CA-31
    +DoD EMAIL CA-32
    +DoD EMAIL CA-33
    +DoD EMAIL CA-34
    +DoD EMAIL CA-39
    +DoD EMAIL CA-40
    +DoD EMAIL CA-41
    +DoD EMAIL CA-42
    +DoD EMAIL CA-43
    +DoD EMAIL CA-44
    +DoD EMAIL CA-49
    +DoD EMAIL CA-50
    +DoD EMAIL CA-51
    +DoD EMAIL CA-52
    +DoD SW CA-53
    +DoD SW CA-54
    +DoD SW CA-55
    +DoD SW CA-56
    +DoD SW CA-57
    +DoD SW CA-58
    + + + + +

    UNCLASSIFIED
    + + diff --git a/tests/fixtures/test.der.crl b/tests/fixtures/test.der.crl new file mode 100644 index 00000000..dc8310f2 --- /dev/null +++ b/tests/fixtures/test.der.crl @@ -0,0 +1,14 @@ +-----BEGIN X509 CRL----- +MIICDjCB9zANBgkqhkiG9w0BAQQFADCBjTELMAkGA1UEBhMCVVMxFTATBgNVBAgT +DFBlbm5zeWx2YW5pYTEVMBMGA1UEBxMMUGhpbGFkZWxwaGlhMRAwDgYDVQQKEwdG +YXV4RG9EMQswCQYDVQQLEwJQVzERMA8GA1UEAxMIRmF1eCBEb0QxHjAcBgkqhkiG +9w0BCQEWD2ZhdXhkb2RAZG9kLmNvbRcNMTgwNzMwMjEzMzQ3WhcNMTgwODI5MjEz +MzQ3WjA4MBoCCQCoSzDcVuoXYxcNMTgwNzMwMjEzMzAxWjAaAgkA3u1dCnHnJ9kX +DTE4MDYyMDIwNDYxMVowDQYJKoZIhvcNAQEEBQADggEBAIYH2GbZUfqbqAaNJW2W +jREAbHnk2x5PSUri/YL9nH7ZAviZARtjuy5WKmu4hhAc/RwarwITT3NtP3BddLTF +RCd1vdsKWh4s7QqEZQSXaXb4/uEP2rsLVmbWoZxIp2gXrQXSA5kkKx0N3pY3kETg +vuMax8E2GdoJLNJe0xm0+hk4C9HcOf+WPL26n1+J4ZIhKf67BfZli0eFZue1PeVA +Ow2XBnKI/yw4GA9+OFcZ4JzJnRMdx/O9bjbzj3gkx9t22Ukzo66BVklplqWmb4YQ +PaRl0LxZtP/GLE6Ej8QmwK2SC26M60F6ceIFtgY3gor5J3oWmXGYz5xm4PWLj5fp +v2w= +-----END X509 CRL----- diff --git a/tests/handlers/test_financial_verification.py b/tests/handlers/test_financial_verification.py deleted file mode 100644 index 6e60bb4e..00000000 --- a/tests/handlers/test_financial_verification.py +++ /dev/null @@ -1,84 +0,0 @@ -import re -import pytest -import tornado -import urllib -from tests.mocks import MOCK_REQUEST, MOCK_USER, MOCK_VALID_PE_ID - - -class TestPENumberInForm: - - required_data = { - "pe_id": "123", - "task_order_id": "1234567899C0001", - "fname_co": "Contracting", - "lname_co": "Officer", - "email_co": "jane@mail.mil", - "office_co": "WHS", - "fname_cor": "Officer", - "lname_cor": "Representative", - "email_cor": "jane@mail.mil", - "office_cor": "WHS", - "funding_type": "RDTE", - "funding_type_other": "other", - "clin_0001": "50,000", - "clin_0003": "13,000", - "clin_1001": "30,000", - "clin_1003": "7,000", - "clin_2001": "30,000", - "clin_2003": "7,000", - } - - def _set_monkeypatches(self, monkeypatch): - monkeypatch.setattr( - "atst.handlers.request_financial_verification.RequestFinancialVerification.get_current_user", lambda s: MOCK_USER - ) - monkeypatch.setattr( - "atst.handlers.request_financial_verification.RequestFinancialVerification.check_xsrf_cookie", lambda s: True - ) - monkeypatch.setattr("atst.forms.request.RequestForm.validate", lambda s: True) - - @tornado.gen.coroutine - def submit_data(self, http_client, base_url, data): - response = yield http_client.fetch( - base_url + "/requests/verify/{}".format(MOCK_REQUEST["id"]), - method="POST", - headers={"Content-Type": "application/x-www-form-urlencoded"}, - body=urllib.parse.urlencode(data), - follow_redirects=False, - raise_error=False, - ) - return response - - @pytest.mark.gen_test - def test_submit_request_form_with_invalid_pe_id(self, monkeypatch, http_client, base_url): - self._set_monkeypatches(monkeypatch) - - response = yield self.submit_data(http_client, base_url, self.required_data) - - assert "We couldn\'t find that PE number" in response.body.decode() - assert response.code == 200 - assert "/requests/verify" in response.effective_url - - @pytest.mark.gen_test - def test_submit_request_form_with_unchanged_pe_id(self, monkeypatch, http_client, base_url): - self._set_monkeypatches(monkeypatch) - - data = dict(self.required_data) - data['pe_id'] = MOCK_REQUEST['body']['financial_verification']['pe_id'] - - response = yield self.submit_data(http_client, base_url, data) - - assert response.code == 302 - assert response.headers.get("Location") == "/requests/financial_verification_submitted" - - @pytest.mark.gen_test - def test_submit_request_form_with_new_valid_pe_id(self, monkeypatch, http_client, base_url): - self._set_monkeypatches(monkeypatch) - - data = dict(self.required_data) - data['pe_id'] = MOCK_VALID_PE_ID - - response = yield self.submit_data(http_client, base_url, data) - - assert response.code == 302 - assert response.headers.get("Location") == "/requests/financial_verification_submitted" diff --git a/tests/handlers/test_request_new.py b/tests/handlers/test_request_new.py deleted file mode 100644 index dfa57cab..00000000 --- a/tests/handlers/test_request_new.py +++ /dev/null @@ -1,45 +0,0 @@ -import re -import pytest -import tornado -import urllib -from tests.mocks import MOCK_USER - -ERROR_CLASS = "alert--error" - -@pytest.mark.gen_test -def test_submit_invalid_request_form(monkeypatch, http_client, base_url): - monkeypatch.setattr( - "atst.handlers.request_new.RequestNew.get_current_user", lambda s: MOCK_USER - ) - monkeypatch.setattr( - "atst.handlers.request_new.RequestNew.check_xsrf_cookie", lambda s: True - ) - # this just needs to send a known invalid form value - response = yield http_client.fetch( - base_url + "/requests/new", - method="POST", - headers={"Content-Type": "application/x-www-form-urlencoded"}, - body="total_ram=5", - ) - assert response.effective_url == base_url + "/requests/new" - assert re.search(ERROR_CLASS, response.body.decode()) - - -@pytest.mark.gen_test -def test_submit_valid_request_form(monkeypatch, http_client, base_url): - monkeypatch.setattr( - "atst.handlers.request_new.RequestNew.get_current_user", lambda s: MOCK_USER - ) - monkeypatch.setattr( - "atst.handlers.request_new.RequestNew.check_xsrf_cookie", lambda s: True - ) - monkeypatch.setattr("atst.forms.request.RequestForm.validate", lambda s: True) - - # this just needs to send a known invalid form value - response = yield http_client.fetch( - base_url + "/requests/new", - method="POST", - headers={"Content-Type": "application/x-www-form-urlencoded"}, - body="meaning=42", - ) - assert "/requests/new/2" in response.effective_url diff --git a/tests/handlers/test_request_submit.py b/tests/handlers/test_request_submit.py deleted file mode 100644 index 0f60c1a1..00000000 --- a/tests/handlers/test_request_submit.py +++ /dev/null @@ -1,49 +0,0 @@ -import pytest -from tests.mocks import MOCK_USER - -ERROR_CLASS = "usa-input-error-message" -APPROVED_MOCK_REQUEST = { - "status": "approved" -} - -@pytest.mark.gen_test -def test_submit_reviewed_request(monkeypatch, http_client, base_url): - monkeypatch.setattr( - "atst.handlers.request_submit.RequestsSubmit.get_current_user", lambda s: MOCK_USER - ) - monkeypatch.setattr( - "atst.handlers.request_submit.RequestsSubmit.check_xsrf_cookie", lambda s: True - ) - # this just needs to send a known invalid form value - response = yield http_client.fetch( - base_url + "/requests/submit/1", - method="POST", - headers={"Content-Type": "application/x-www-form-urlencoded"}, - body="", - raise_error=False, - follow_redirects=False - ) - assert response.headers["Location"] == "/requests" - - -@pytest.mark.gen_test -def test_submit_autoapproved_reviewed_request(monkeypatch, http_client, base_url): - monkeypatch.setattr( - "atst.handlers.request_submit.RequestsSubmit.get_current_user", lambda s: MOCK_USER - ) - monkeypatch.setattr( - "atst.handlers.request_submit.RequestsSubmit.check_xsrf_cookie", lambda s: True - ) - monkeypatch.setattr( - "tests.mocks.MOCK_REQUEST", APPROVED_MOCK_REQUEST - ) - # this just needs to send a known invalid form value - response = yield http_client.fetch( - base_url + "/requests/submit/1", - method="POST", - headers={"Content-Type": "application/x-www-form-urlencoded"}, - body="", - raise_error=False, - follow_redirects=False - ) - assert response.headers["Location"] == "/requests?modal=True" diff --git a/tests/mocks.py b/tests/mocks.py index a7290a03..1e44f96e 100644 --- a/tests/mocks.py +++ b/tests/mocks.py @@ -1,135 +1,20 @@ -import tornado.gen -from tornado.httpclient import HTTPRequest, HTTPResponse - -from atst.api_client import ApiClient +from tests.factories import RequestFactory, UserFactory -MOCK_USER = { - "id": "9cb348f0-8102-4962-88c4-dac8180c904c", - "email": "fake.user@mail.com", - "first_name": "Fake", - "last_name": "User", -} - - -class MockApiClient(ApiClient): - - def __init__(self, service): - self.service = service - - @tornado.gen.coroutine - def get(self, path, **kwargs): - return self._get_response("GET", path) - - @tornado.gen.coroutine - def put(self, path, **kwargs): - return self._get_response("PUT", path) - - @tornado.gen.coroutine - def patch(self, path, **kwargs): - return self._get_response("PATCH", path) - - @tornado.gen.coroutine - def post(self, path, **kwargs): - return self._get_response("POST", path) - - @tornado.gen.coroutine - def delete(self, path, **kwargs): - return self._get_response("DELETE", path) - - def _get_response(self, verb, path, code=200, json=None): - response = HTTPResponse( - request=HTTPRequest(path, verb), - code=code, - headers={"Content-Type": "application/json"}, - ) - - setattr(response, "ok", 200 <= code < 300) - if json: - setattr(response, "json", json) - - return response - - -MOCK_REQUEST = { - "id": "66b8ef71-86d3-48ef-abc2-51bfa1732b6b", - "creator": "49903ae7-da4a-49bf-a6dc-9dff5d004238", - "body": { +MOCK_USER = UserFactory.create() +MOCK_REQUEST = RequestFactory.create( + creator=MOCK_USER.id, + body={ "financial_verification": { "pe_id": "0203752A", }, - }, - "status": "incomplete" -} - -class MockRequestsClient(MockApiClient): - - @tornado.gen.coroutine - def get(self, path, **kwargs): - return self._get_response("GET", path, 200, json=MOCK_REQUEST) - - @tornado.gen.coroutine - def post(self, path, **kwargs): - return self._get_response("POST", path, 202, json=MOCK_REQUEST) - + } +) +DOD_SDN_INFO = { + 'first_name': 'ART', + 'last_name': 'GARFUNKEL', + 'dod_id': '5892460358' + } +DOD_SDN = f"CN={DOD_SDN_INFO['last_name']}.{DOD_SDN_INFO['first_name']}.G.{DOD_SDN_INFO['dod_id']},OU=OTHER,OU=PKI,OU=DoD,O=U.S. Government,C=US" MOCK_VALID_PE_ID = "8675309U" - - -class MockFundzClient(MockApiClient): - - @tornado.gen.coroutine - def get(self, path, **kwargs): - if path.endswith(MOCK_VALID_PE_ID): - return self._get_response("GET", path, 200) - else: - return self._get_response("GET", path, 404) - - -class MockAuthzClient(MockApiClient): - _json = { - "atat_permissions": [ - "view_original_jedi_request", - "review_and_approve_jedi_workspace_request", - "modify_atat_role_permissions", - "create_csp_role", - "delete_csp_role", - "deactivate_csp_role", - "modify_csp_role_permissions", - "view_usage_report", - "view_usage_dollars", - "add_and_assign_csp_roles", - "remove_csp_roles", - "request_new_csp_role", - "assign_and_unassign_atat_role", - "view_assigned_atat_role_configurations", - "view_assigned_csp_role_configurations", - "deactivate_workspace", - "view_atat_permissions", - "transfer_ownership_of_workspace", - "add_application_in_workspace", - "delete_application_in_workspace", - "deactivate_application_in_workspace", - "view_application_in_workspace", - "rename_application_in_workspace", - "add_environment_in_application", - "delete_environment_in_application", - "deactivate_environment_in_application", - "view_environment_in_application", - "rename_environment_in_application", - "add_tag_to_workspace", - "remove_tag_from_workspace", - ], - "atat_role": "ccpo", - "id": "164497f6-c1ea-4f42-a5ef-101da278c012", - "username": None, - "workspace_roles": [], - } - - @tornado.gen.coroutine - def post(self, path, **kwargs): - return self._get_response("POST", path, 200, json=self._json) - - @tornado.gen.coroutine - def get(self, path, **kwargs): - return self._get_response("POST", path, 200, json=self._json) diff --git a/tests/routes/test_financial_verification.py b/tests/routes/test_financial_verification.py new file mode 100644 index 00000000..60f0f9b0 --- /dev/null +++ b/tests/routes/test_financial_verification.py @@ -0,0 +1,76 @@ +import re +import pytest +import urllib +from tests.mocks import MOCK_REQUEST, MOCK_USER +from tests.factories import PENumberFactory + + +class TestPENumberInForm: + + required_data = { + "pe_id": "123", + "task_order_id": "1234567899C0001", + "fname_co": "Contracting", + "lname_co": "Officer", + "email_co": "jane@mail.mil", + "office_co": "WHS", + "fname_cor": "Officer", + "lname_cor": "Representative", + "email_cor": "jane@mail.mil", + "office_cor": "WHS", + "funding_type": "RDTE", + "funding_type_other": "other", + "clin_0001": "50,000", + "clin_0003": "13,000", + "clin_1001": "30,000", + "clin_1003": "7,000", + "clin_2001": "30,000", + "clin_2003": "7,000", + } + + def _set_monkeypatches(self, monkeypatch): + monkeypatch.setattr("atst.forms.financial.FinancialForm.validate", lambda s: True) + monkeypatch.setattr("atst.domain.requests.Requests.get", lambda i: MOCK_REQUEST) + monkeypatch.setattr("atst.domain.auth.get_current_user", lambda *args: MOCK_USER) + + def submit_data(self, client, data): + response = client.post( + "/requests/verify/{}".format(MOCK_REQUEST.id), + headers={"Content-Type": "application/x-www-form-urlencoded"}, + data=urllib.parse.urlencode(data), + follow_redirects=False, + ) + return response + + def test_submit_request_form_with_invalid_pe_id(self, monkeypatch, client): + self._set_monkeypatches(monkeypatch) + + response = self.submit_data(client, self.required_data) + + assert "We couldn\'t find that PE number" in response.data.decode() + assert response.status_code == 200 + + def test_submit_request_form_with_unchanged_pe_id(self, monkeypatch, client): + self._set_monkeypatches(monkeypatch) + + data = dict(self.required_data) + data['pe_id'] = MOCK_REQUEST.body['financial_verification']['pe_id'] + + response = self.submit_data(client, data) + + assert response.status_code == 302 + assert "/requests/financial_verification_submitted" in response.headers.get("Location") + + def test_submit_request_form_with_new_valid_pe_id(self, session, monkeypatch, client): + self._set_monkeypatches(monkeypatch) + pe = PENumberFactory.create(number="8675309U", description="sample PE number") + session.add(pe) + session.commit() + + data = dict(self.required_data) + data['pe_id'] = pe.number + + response = self.submit_data(client, data) + + assert response.status_code == 302 + assert "/requests/financial_verification_submitted" in response.headers.get("Location") diff --git a/tests/routes/test_request_new.py b/tests/routes/test_request_new.py new file mode 100644 index 00000000..0927f1be --- /dev/null +++ b/tests/routes/test_request_new.py @@ -0,0 +1,29 @@ +import re +import pytest +import urllib +from tests.mocks import MOCK_USER, MOCK_REQUEST +from tests.factories import RequestFactory + + +ERROR_CLASS = "alert--error" + +def test_submit_invalid_request_form(monkeypatch, client, user_session): + user_session() + response = client.post( + "/requests/new/1", + headers={"Content-Type": "application/x-www-form-urlencoded"}, + data="total_ram=5", + ) + assert re.search(ERROR_CLASS, response.data.decode()) + + +def test_submit_valid_request_form(monkeypatch, client, user_session): + user_session() + monkeypatch.setattr("atst.forms.request.RequestForm.validate", lambda s: True) + + response = client.post( + "/requests/new/1", + headers={"Content-Type": "application/x-www-form-urlencoded"}, + data="meaning=42", + ) + assert "/requests/new/2" in response.headers.get("Location") diff --git a/tests/routes/test_request_submit.py b/tests/routes/test_request_submit.py new file mode 100644 index 00000000..428e056e --- /dev/null +++ b/tests/routes/test_request_submit.py @@ -0,0 +1,38 @@ +import pytest +from tests.mocks import MOCK_USER +from tests.factories import RequestFactory + + +def _mock_func(*args, **kwargs): + return RequestFactory.create() + + +def test_submit_reviewed_request(monkeypatch, client, user_session): + user_session() + monkeypatch.setattr("atst.domain.requests.Requests.get", _mock_func) + monkeypatch.setattr("atst.domain.requests.Requests.submit", _mock_func) + monkeypatch.setattr("atst.models.request.Request.status", "pending") + # this just needs to send a known invalid form value + response = client.post( + "/requests/submit/1", + headers={"Content-Type": "application/x-www-form-urlencoded"}, + data="", + follow_redirects=False, + ) + assert "/requests" in response.headers["Location"] + assert "modal" not in response.headers["Location"] + + +def test_submit_autoapproved_reviewed_request(monkeypatch, client, user_session): + user_session() + monkeypatch.setattr("atst.domain.requests.Requests.get", _mock_func) + monkeypatch.setattr("atst.domain.requests.Requests.submit", _mock_func) + monkeypatch.setattr("atst.models.request.Request.status", "approved") + # this just needs to send a known invalid form value + response = client.post( + "/requests/submit/1", + headers={"Content-Type": "application/x-www-form-urlencoded"}, + data="", + follow_redirects=False, + ) + assert "/requests?modal=True" in response.headers["Location"] diff --git a/tests/test_api_client.py b/tests/test_api_client.py deleted file mode 100644 index 5b1880cb..00000000 --- a/tests/test_api_client.py +++ /dev/null @@ -1,10 +0,0 @@ -import pytest - -from atst.api_client import ApiClient - - -@pytest.mark.gen_test -def test_api_client(http_client, base_url): - client = ApiClient(base_url) - response = yield client.get("") - assert response.code == 200 diff --git a/tests/test_auth.py b/tests/test_auth.py index 7480015e..69cb3166 100644 --- a/tests/test_auth.py +++ b/tests/test_auth.py @@ -1,81 +1,90 @@ -import re -import pytest -import tornado.web -import tornado.gen +from flask import session, url_for +from .mocks import DOD_SDN + MOCK_USER = {"id": "438567dd-25fa-4d83-a8cc-8aa8366cb24a"} -@tornado.gen.coroutine + + def _fetch_user_info(c, t): return MOCK_USER -@pytest.mark.gen_test -def test_redirects_when_not_logged_in(http_client, base_url): - response = yield http_client.fetch( - base_url + "/home", raise_error=False, follow_redirects=False - ) - location = response.headers["Location"] - assert response.code == 302 - assert response.error - assert re.match("/\??", location) +def test_successful_login_redirect(client, monkeypatch): + monkeypatch.setattr("atst.routes._is_valid_certificate", lambda *args: True) -@pytest.mark.gen_test -def test_redirects_when_session_does_not_exist(monkeypatch, http_client, base_url): - monkeypatch.setattr("atst.handlers.main.Main.get_secure_cookie", lambda s,c: 'stale cookie!') - response = yield http_client.fetch( - base_url + "/home", raise_error=False, follow_redirects=False - ) - location = response.headers["Location"] - cookie = response.headers._dict.get('Set-Cookie') - # should clear session cookie - assert 'atat=""' in cookie - assert response.code == 302 - assert response.error - assert re.match("/\??", location) - - -@pytest.mark.gen_test -def test_login_with_valid_bearer_token(app, monkeypatch, http_client, base_url): - monkeypatch.setattr("atst.handlers.login_redirect.LoginRedirect._fetch_user_info", _fetch_user_info) - response = yield http_client.fetch( - base_url + "/login-redirect?bearer-token=abc-123", - follow_redirects=False, - raise_error=False, - ) - assert response.headers["Set-Cookie"].startswith("atat") - assert response.headers["Location"] == "/home" - assert response.code == 302 - - -@pytest.mark.gen_test -def test_login_via_dev_endpoint(app, http_client, base_url): - response = yield http_client.fetch( - base_url + "/login-dev", raise_error=False, follow_redirects=False - ) - assert response.headers["Set-Cookie"].startswith("atat") - assert response.code == 302 - assert response.headers["Location"] == "/home" - - -@pytest.mark.gen_test -@pytest.mark.skip(reason="need to work out auth error user paths") -def test_login_with_invalid_bearer_token(http_client, base_url): - _response = yield http_client.fetch( - base_url + "/home", - raise_error=False, - headers={"Cookie": "bearer-token=anything"}, + resp = client.get( + "/login-redirect", + environ_base={ + "HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS", "HTTP_X_SSL_CLIENT_S_DN": DOD_SDN + }, ) -@pytest.mark.gen_test -def test_valid_login_creates_session(app, monkeypatch, http_client, base_url): - monkeypatch.setattr("atst.handlers.login_redirect.LoginRedirect._fetch_user_info", _fetch_user_info) - assert len(app.sessions.sessions) == 0 - yield http_client.fetch( - base_url + "/login-redirect?bearer-token=abc-123", - follow_redirects=False, - raise_error=False, + assert resp.status_code == 302 + assert "home" in resp.headers["Location"] + assert session["user_id"] + + +def test_unsuccessful_login_redirect(client, monkeypatch): + resp = client.get("/login-redirect") + + assert resp.status_code == 302 + assert "unauthorized" in resp.headers["Location"] + assert "user_id" not in session + + +# checks that all of the routes in the app are protected by auth + + +def test_routes_are_protected(client, app): + for rule in app.url_map.iter_rules(): + args = [1] * len(rule.arguments) + mock_args = dict(zip(rule.arguments, args)) + _n, route = rule.build(mock_args) + if route in UNPROTECTED_ROUTES or "/static" in route: + continue + + if "GET" in rule.methods: + resp = client.get(route) + assert resp.status_code == 302 + assert resp.headers["Location"] == "http://localhost/" + + if "POST" in rule.methods: + resp = client.post(route) + assert resp.status_code == 302 + assert resp.headers["Location"] == "http://localhost/" + + +UNPROTECTED_ROUTES = ["/", "/login-dev", "/login-redirect", "/unauthorized"] + +# this implicitly relies on the test config and test CRL in tests/fixtures/crl + + +def test_crl_validation_on_login(client): + good_cert = open("ssl/client-certs/atat.mil.crt", "rb").read() + bad_cert = open("ssl/client-certs/bad-atat.mil.crt", "rb").read() + + # bad cert is on the test CRL + resp = client.get( + "/login-redirect", + environ_base={ + "HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS", + "HTTP_X_SSL_CLIENT_S_DN": DOD_SDN, + "HTTP_X_SSL_CLIENT_CERT": bad_cert.decode(), + }, ) - assert len(app.sessions.sessions) == 1 - session = list(app.sessions.sessions.values())[0] - assert "atat_permissions" in session["user"] - assert isinstance(session["user"]["atat_permissions"], list) + assert resp.status_code == 302 + assert "unauthorized" in resp.headers["Location"] + assert "user_id" not in session + + # good cert is not on the test CRL, passes + resp = client.get( + "/login-redirect", + environ_base={ + "HTTP_X_SSL_CLIENT_VERIFY": "SUCCESS", + "HTTP_X_SSL_CLIENT_S_DN": DOD_SDN, + "HTTP_X_SSL_CLIENT_CERT": good_cert.decode(), + }, + ) + assert resp.status_code == 302 + assert "home" in resp.headers["Location"] + assert session["user_id"] diff --git a/tests/test_basic.py b/tests/test_basic.py index dd2b9a21..67df4c9f 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -1,7 +1,3 @@ -import pytest - - -@pytest.mark.gen_test -def test_hello_world(http_client, base_url): - response = yield http_client.fetch(base_url) - assert response.code == 200 +def test_hello_world(client): + response = client.get("/") + assert response.status_code == 200 diff --git a/tests/test_integration.py b/tests/test_integration.py index aa97c2d6..e8fa6348 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -1,13 +1,14 @@ import pytest -import tornado from tests.mocks import MOCK_USER -from atst.handlers.request_new import JEDIRequestFlow +from atst.routes.requests.jedi_request_flow import JEDIRequestFlow -SCREENS = JEDIRequestFlow(None, None, 3).screens +@pytest.fixture +def screens(app): + return JEDIRequestFlow(3).screens -@pytest.mark.gen_test -def test_stepthrough_request_form(monkeypatch, http_client, base_url): +@pytest.mark.skip() +def test_stepthrough_request_form(monkeypatch, screens, client): monkeypatch.setattr( "atst.handlers.request_new.RequestNew.get_current_user", lambda s: MOCK_USER ) @@ -18,29 +19,28 @@ def test_stepthrough_request_form(monkeypatch, http_client, base_url): "atst.handlers.request_new.JEDIRequestFlow.validate", lambda s: True ) - @tornado.gen.coroutine def take_a_step(inc, req=None): - req_url = base_url + "/requests/new/{}".format(inc) + req_url = "/requests/new/{}".format(inc) if req: req_url += "/" + req - response = yield http_client.fetch( + response = client.post( req_url, - method="POST", headers={"Content-Type": "application/x-www-form-urlencoded"}, - body="meaning=42", + data="meaning=42", ) return response # GET the initial form - response = yield http_client.fetch(base_url + "/requests/new", method="GET") - assert SCREENS[0]["title"] in response.body.decode() + response = client.get("/requests/new") + assert screens[0]["title"] in response.data.decode() # POST to each of the form pages up until review and submit req_id = None - for i in range(1, len(SCREENS)): - resp = yield take_a_step(i, req=req_id) + for i in range(1, len(screens)): + resp = take_a_step(i, req=req_id) + __import__('ipdb').set_trace() req_id = resp.effective_url.split("/")[-1] - screen_title = SCREENS[i]["title"].replace("&", "&") + screen_title = screens[i]["title"].replace("&", "&") assert "/requests/new/{}/{}".format(i + 1, req_id) in resp.effective_url - assert screen_title in resp.body.decode() + assert screen_title in resp.data.decode() diff --git a/tests/test_routes.py b/tests/test_routes.py index e6a9122c..74860472 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -1,18 +1,17 @@ import pytest - -@pytest.mark.gen_test -def test_routes(http_client, base_url): - for path in ( +@pytest.mark.parametrize("path", ( "/", "/home", "/workspaces", "/requests", - "/requests/new", "/requests/new/1", "/users", "/reports", "/calculator", - ): - response = yield http_client.fetch(base_url + path) - assert response.code == 200 + )) +def test_routes(path, client, user_session): + user_session() + + response = client.get(path) + assert response.status_code == 200 diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..b8e561fc --- /dev/null +++ b/yarn.lock @@ -0,0 +1,6846 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.stat@^1.0.1": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.0.tgz#50c1e2260ac0ed9439a181de3725a0168d59c48a" + +"@types/node@^8.5.5": + version "8.10.23" + resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.23.tgz#e5ccfdafff42af5397c29669b6d7d65f7d629a00" + +JSONStream@^1.0.3, JSONStream@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.3.tgz#27b4b8fbbfeab4e71bcf551e7f27be8d952239bf" + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1, abbrev@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + +acorn-dynamic-import@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz#901ceee4c7faaef7e07ad2a47e890675da50a278" + dependencies: + acorn "^5.0.0" + +acorn-node@^1.2.0, acorn-node@^1.3.0, acorn-node@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.5.2.tgz#2ca723df19d997b05824b69f6c7fb091fc42c322" + dependencies: + acorn "^5.7.1" + acorn-dynamic-import "^3.0.0" + xtend "^4.0.1" + +acorn@^5.0.0, acorn@^5.2.1, acorn@^5.7.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + +agent-base@4, agent-base@^4.1.0, agent-base@~4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + dependencies: + es6-promisify "^5.0.0" + +agentkeepalive@^3.4.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.1.tgz#4eba75cf2ad258fc09efd506cdb8d8c2971d35a4" + dependencies: + humanize-ms "^1.2.1" + +ajv@^4.9.1: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + +alphanum-sort@^1.0.0, alphanum-sort@^1.0.1, alphanum-sort@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + dependencies: + string-width "^2.0.0" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + dependencies: + color-convert "^1.9.0" + +ansi-to-html@^0.6.4: + version "0.6.6" + resolved "https://registry.yarnpkg.com/ansi-to-html/-/ansi-to-html-0.6.6.tgz#58a8d04b87ec9a85e3ad273c12a5fbc7147b9c42" + dependencies: + entities "^1.1.1" + +ansicolors@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979" + +ansistyles@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +aproba@^1.0.3, aproba@^1.1.1, aproba@^1.1.2, aproba@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +"aproba@^1.1.2 || 2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + +archy@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + +array-filter@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-0.0.1.tgz#7da8cf2e26628ed732803581fd21f67cacd2eeec" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + +array-foreach@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-foreach/-/array-foreach-1.0.2.tgz#cd36e42f0f482108c406b35c3612a8970b2fccea" + +array-map@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-map/-/array-map-0.0.0.tgz#88a2bab73d1cf7bcd5c1b118a003f66f665fa662" + +array-reduce@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/array-reduce/-/array-reduce-0.0.0.tgz#173899d3ffd1c7d9383e4479525dbe278cab5f2b" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +assert@^1.1.1, assert@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91" + dependencies: + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async-foreach@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" + +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +atob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.1.tgz#ae2d5a729477f289d60dd7f96a6314a22dd6c22a" + +autoprefixer@^6.3.1: + version "6.7.7" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014" + dependencies: + browserslist "^1.7.6" + caniuse-db "^1.0.30000634" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^5.2.16" + postcss-value-parser "^3.2.3" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-core@^6.25.0, babel-core@^6.26.0: + version "6.26.3" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" + dependencies: + babel-code-frame "^6.26.0" + babel-generator "^6.26.0" + babel-helpers "^6.24.1" + babel-messages "^6.23.0" + babel-register "^6.26.0" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + convert-source-map "^1.5.1" + debug "^2.6.9" + json5 "^0.5.1" + lodash "^4.17.4" + minimatch "^3.0.4" + path-is-absolute "^1.0.1" + private "^0.1.8" + slash "^1.0.0" + source-map "^0.5.7" + +babel-generator@^6.25.0, babel-generator@^6.26.0: + version "6.26.1" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" + dependencies: + 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" + +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" + dependencies: + babel-helper-explode-assignable-expression "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-builder-react-jsx@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz#39ff8313b75c8b65dceff1f31d383e0ff2a408a0" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + esutils "^2.0.2" + +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-define-map@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" + dependencies: + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-helper-regex@^6.24.1: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" + dependencies: + babel-runtime "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" + dependencies: + babel-helper-optimise-call-expression "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" + dependencies: + babel-helper-remap-async-to-generator "^6.24.1" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.23.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" + dependencies: + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + lodash "^4.17.4" + +babel-plugin-transform-es2015-classes@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" + dependencies: + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-destructuring@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-for-of@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" + dependencies: + babel-helper-function-name "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1, babel-plugin-transform-es2015-modules-commonjs@^6.26.0: + version "6.26.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" + dependencies: + babel-plugin-transform-strict-mode "^6.24.1" + babel-runtime "^6.26.0" + babel-template "^6.26.0" + babel-types "^6.26.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" + dependencies: + babel-helper-hoist-variables "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" + dependencies: + babel-helper-replace-supers "^6.24.1" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.23.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" + dependencies: + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" + babel-runtime "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" + dependencies: + babel-helper-regex "^6.24.1" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" + dependencies: + babel-helper-builder-react-jsx "^6.24.1" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" + dependencies: + regenerator-transform "^0.10.0" + +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.24.1" + +babel-preset-env@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^3.2.6" + invariant "^2.2.2" + semver "^5.3.0" + +babel-register@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" + dependencies: + babel-core "^6.26.0" + babel-runtime "^6.26.0" + core-js "^2.5.0" + home-or-tmp "^2.0.0" + lodash "^4.17.4" + mkdirp "^0.5.1" + source-map-support "^0.4.15" + +babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-template@^6.24.1, babel-template@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" + dependencies: + babel-runtime "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + lodash "^4.17.4" + +babel-traverse@^6.24.1, babel-traverse@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + dependencies: + 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" + +babel-types@^6.15.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon-walk@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/babylon-walk/-/babylon-walk-1.0.2.tgz#3b15a5ddbb482a78b4ce9c01c8ba181702d9d6ce" + dependencies: + babel-runtime "^6.11.6" + babel-types "^6.15.0" + lodash.clone "^4.5.0" + +babylon@^6.17.4, babylon@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + +balanced-match@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-js@^1.0.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + dependencies: + 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" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + dependencies: + tweetnacl "^0.14.3" + +bin-links@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-1.1.2.tgz#fb74bd54bae6b7befc6c6221f25322ac830d9757" + dependencies: + bluebird "^3.5.0" + cmd-shim "^2.0.2" + gentle-fs "^2.0.0" + graceful-fs "^4.1.11" + write-file-atomic "^2.3.0" + +binary-extensions@^1.0.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" + +bindings@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@^3.0.5, bluebird@^3.5.0, bluebird@^3.5.1, bluebird@~3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boxen@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^2.0.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^1.2.0" + widest-line "^2.0.0" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.0, braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + dependencies: + 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" + +brfs@^1.2.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/brfs/-/brfs-1.6.1.tgz#b78ce2336d818e25eea04a0947cba6d4fb8849c3" + dependencies: + quote-stream "^1.0.1" + resolve "^1.1.5" + static-module "^2.2.0" + through2 "^2.0.0" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + +browser-pack@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/browser-pack/-/browser-pack-6.1.0.tgz#c34ba10d0b9ce162b5af227c7131c92c2ecd5774" + dependencies: + JSONStream "^1.0.3" + combine-source-map "~0.8.0" + defined "^1.0.0" + safe-buffer "^5.1.1" + through2 "^2.0.0" + umd "^3.0.0" + +browser-resolve@^1.11.0, browser-resolve@^1.7.0: + version "1.11.3" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" + dependencies: + resolve "1.1.7" + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + dependencies: + 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@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + dependencies: + 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@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + dependencies: + pako "~1.0.5" + +browserify-zlib@~0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d" + dependencies: + pako "~0.2.0" + +browserify@^13.0.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/browserify/-/browserify-13.3.0.tgz#b5a9c9020243f0c70e4675bec8223bc627e415ce" + dependencies: + JSONStream "^1.0.3" + assert "^1.4.0" + browser-pack "^6.0.1" + browser-resolve "^1.11.0" + browserify-zlib "~0.1.2" + buffer "^4.1.0" + cached-path-relative "^1.0.0" + concat-stream "~1.5.1" + console-browserify "^1.1.0" + constants-browserify "~1.0.0" + crypto-browserify "^3.0.0" + defined "^1.0.0" + deps-sort "^2.0.0" + domain-browser "~1.1.0" + duplexer2 "~0.1.2" + events "~1.1.0" + glob "^7.1.0" + has "^1.0.0" + htmlescape "^1.1.0" + https-browserify "~0.0.0" + inherits "~2.0.1" + insert-module-globals "^7.0.0" + labeled-stream-splicer "^2.0.0" + module-deps "^4.0.8" + os-browserify "~0.1.1" + parents "^1.0.1" + path-browserify "~0.0.0" + process "~0.11.0" + punycode "^1.3.2" + querystring-es3 "~0.2.0" + read-only-stream "^2.0.0" + readable-stream "^2.0.2" + resolve "^1.1.4" + shasum "^1.0.0" + shell-quote "^1.6.1" + stream-browserify "^2.0.0" + stream-http "^2.0.0" + string_decoder "~0.10.0" + subarg "^1.0.0" + syntax-error "^1.1.1" + through2 "^2.0.0" + timers-browserify "^1.0.1" + tty-browserify "~0.0.0" + url "~0.11.0" + util "~0.10.1" + vm-browserify "~0.0.1" + xtend "^4.0.0" + +browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + +browserslist@^3.2.6: + version "3.2.8" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" + dependencies: + caniuse-lite "^1.0.30000844" + electron-to-chromium "^1.3.47" + +browserslist@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.0.1.tgz#61c05ce2a5843c7d96166408bc23d58b5416e818" + dependencies: + caniuse-lite "^1.0.30000865" + electron-to-chromium "^1.3.52" + node-releases "^1.0.0-alpha.10" + +buffer-equal@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + +buffer@^4.1.0, buffer@^4.3.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-modules@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + +byte-size@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-4.0.3.tgz#b7c095efc68eadf82985fccd9a2df43a74fa2ccd" + +cacache@^10.0.4: + version "10.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-10.0.4.tgz#6452367999eff9d4188aefd9a14e9d7c6a263460" + dependencies: + bluebird "^3.5.1" + chownr "^1.0.1" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.1" + mississippi "^2.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.2" + ssri "^5.2.4" + unique-filename "^1.1.0" + y18n "^4.0.0" + +cacache@^11.0.1, cacache@^11.0.2, cacache@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-11.1.0.tgz#3d76dbc2e9da413acaad2557051960a4dad3e1a4" + dependencies: + bluebird "^3.5.1" + chownr "^1.0.1" + figgy-pudding "^3.1.0" + glob "^7.1.2" + graceful-fs "^4.1.11" + lru-cache "^4.1.3" + 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.0" + unique-filename "^1.1.0" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + dependencies: + 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" + +cached-path-relative@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.0.1.tgz#d09c4b52800aa4c078e2dd81a869aac90d2e54e7" + +call-limit@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/call-limit/-/call-limit-1.1.0.tgz#6fd61b03f3da42a2cd0ec2b60f02bd0e71991fea" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + +caniuse-api@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" + dependencies: + browserslist "^1.3.6" + caniuse-db "^1.0.30000529" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: + version "1.0.30000872" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000872.tgz#3f6e53b63d373768bf99e896133d66ef89c49999" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000865: + version "1.0.30000865" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000865.tgz#70026616e8afe6e1442f8bb4e1092987d81a2f25" + +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + 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" + +chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chokidar@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26" + dependencies: + anymatch "^2.0.0" + async-each "^1.0.0" + braces "^2.3.0" + glob-parent "^3.1.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + lodash.debounce "^4.0.8" + normalize-path "^2.1.1" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + upath "^1.0.5" + optionalDependencies: + fsevents "^1.2.2" + +chownr@^1.0.1, chownr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.0.1.tgz#e2a75042a9551908bebd25b8523d5f9769d79181" + +ci-info@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" + +cidr-regex@^2.0.8: + version "2.0.9" + resolved "https://registry.yarnpkg.com/cidr-regex/-/cidr-regex-2.0.9.tgz#9c17bb2b18e15af07f7d0c3b994b961d687ed1c9" + dependencies: + ip-regex "^2.1.0" + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +clap@^1.0.9: + version "1.2.3" + resolved "https://registry.yarnpkg.com/clap/-/clap-1.2.3.tgz#4f36745b32008492557f46412d66d50cb99bce51" + dependencies: + chalk "^1.1.3" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +classlist-polyfill@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/classlist-polyfill/-/classlist-polyfill-1.2.0.tgz#935bc2dfd9458a876b279617514638bcaa964a2e" + +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + +cli-columns@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-3.1.2.tgz#6732d972979efc2ae444a1f08e08fa139c96a18e" + dependencies: + string-width "^2.0.0" + strip-ansi "^3.0.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.1.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" + +cli-table3@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" + dependencies: + object-assign "^4.1.0" + string-width "^2.1.1" + optionalDependencies: + colors "^1.1.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + +clone@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" + +clones@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/clones/-/clones-1.1.0.tgz#87e904132d6140c5c0b72006c08c0d05bd7b63b3" + +cmd-shim@^2.0.2, cmd-shim@~2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-2.0.2.tgz#6fcbda99483a8fd15d7d30a196ca69d688a2efdb" + dependencies: + graceful-fs "^4.1.2" + mkdirp "~0.5.0" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +coa@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.4.tgz#a9ef153660d6a86a8bdec0289a5c684d217432fd" + dependencies: + q "^1.1.2" + +coa@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.1.tgz#f3f8b0b15073e35d70263fb1042cb2c023db38af" + dependencies: + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.2.tgz#49881b8fba67df12a96bdf3f56c0aab9e7913147" + dependencies: + color-name "1.1.1" + +color-name@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.1.tgz#4b1415304cf50028ea81643643bd82ea05803689" + +color-name@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +color-string@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-0.3.0.tgz#27d46fb67025c5c2fa25993bfbf579e47841b991" + dependencies: + color-name "^1.0.0" + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^0.11.0: + version "0.11.4" + resolved "https://registry.yarnpkg.com/color/-/color-0.11.4.tgz#6d7b5c74fb65e841cd48792ad1ed5e07b904d764" + dependencies: + clone "^1.0.2" + color-convert "^1.3.0" + color-string "^0.3.0" + +color@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a" + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +colormin@^1.0.5: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colormin/-/colormin-1.1.2.tgz#ea2f7420a72b96881a38aae59ec124a6f7298133" + dependencies: + color "^0.11.0" + css-color-names "0.0.4" + has "^1.0.1" + +colors@^1.1.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.1.tgz#4accdb89cf2cabc7f982771925e9468784f32f3d" + +colors@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + +columnify@~1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" + dependencies: + strip-ansi "^3.0.0" + wcwidth "^1.0.0" + +combine-source-map@^0.8.0, combine-source-map@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/combine-source-map/-/combine-source-map-0.8.0.tgz#a58d0df042c186fcf822a8e8015f5450d2d79a8b" + dependencies: + convert-source-map "~1.1.0" + inline-source-map "~0.6.0" + lodash.memoize "~3.0.3" + source-map "~0.5.3" + +combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + +command-exists@^1.2.6: + version "1.2.7" + resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.7.tgz#16828f0c3ff2b0c58805861ef211b64fc15692a8" + +commander@^2.11.0, commander@^2.9.0, commander@~2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.16.0.tgz#f16390593996ceb4f3eeb020b31d78528f7f8a50" + +commander@~2.14.1: + version "2.14.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" + +component-emitter@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.5.0, concat-stream@^1.5.2, concat-stream@^1.6.1, concat-stream@~1.6.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +concat-stream@~1.5.0, concat-stream@~1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.5.2.tgz#708978624d856af41a5a741defdd261da752c266" + dependencies: + inherits "~2.0.1" + readable-stream "~2.0.0" + typedarray "~0.0.5" + +config-chain@~1.1.11, config-chain@~1.1.5: + version "1.1.11" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.11.tgz#aba09747dfbe4c3e70e766a6e41586e1859fc6f2" + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +configstore@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +console-browserify@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +constants-browserify@^1.0.0, constants-browserify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + +convert-source-map@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" + +convert-source-map@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.1.3.tgz#4829c877e9fe49b3161f3bf3673888e204699860" + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + dependencies: + 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" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + +core-js@^2.4.0, core-js@^2.5.0: + version "2.5.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cosmiconfig@^5.0.0: + version "5.0.5" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.5.tgz#a809e3c2306891ce17ab70359dc8bdf661fe2cd0" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^4.0.0" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + dependencies: + 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@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + dependencies: + 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-spawn@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^6.0.4: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +crypto-browserify@^3.0.0, crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + dependencies: + 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" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + +css-declaration-sorter@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-3.0.1.tgz#d0e3056b0fd88dc1ea9dceff435adbe9c702a7f8" + dependencies: + postcss "^6.0.0" + timsort "^0.3.0" + +css-select-base-adapter@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz#0102b3d14630df86c3eb9fa9f5456270106cf990" + +css-select@~1.3.0-rc0: + version "1.3.0-rc0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.3.0-rc0.tgz#6f93196aaae737666ea1036a8cb14a8fcb7a9231" + dependencies: + boolbase "^1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "^1.0.1" + +css-tree@1.0.0-alpha.29: + version "1.0.0-alpha.29" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" + dependencies: + mdn-data "~1.1.0" + source-map "^0.5.3" + +css-tree@1.0.0-alpha25: + version "1.0.0-alpha25" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha25.tgz#1bbfabfbf6eeef4f01d9108ff2edd0be2fe35597" + dependencies: + mdn-data "^1.0.0" + source-map "^0.5.3" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + +css-url-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/css-url-regex/-/css-url-regex-1.1.0.tgz#83834230cc9f74c457de59eebd1543feeb83b7ec" + +css-what@2.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" + +cssnano-preset-default@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.0.tgz#c334287b4f7d49fb2d170a92f9214655788e3b6b" + dependencies: + css-declaration-sorter "^3.0.0" + cssnano-util-raw-cache "^4.0.0" + postcss "^6.0.0" + postcss-calc "^6.0.0" + postcss-colormin "^4.0.0" + postcss-convert-values "^4.0.0" + postcss-discard-comments "^4.0.0" + postcss-discard-duplicates "^4.0.0" + postcss-discard-empty "^4.0.0" + postcss-discard-overridden "^4.0.0" + postcss-merge-longhand "^4.0.0" + postcss-merge-rules "^4.0.0" + postcss-minify-font-values "^4.0.0" + postcss-minify-gradients "^4.0.0" + postcss-minify-params "^4.0.0" + postcss-minify-selectors "^4.0.0" + postcss-normalize-charset "^4.0.0" + postcss-normalize-display-values "^4.0.0" + postcss-normalize-positions "^4.0.0" + postcss-normalize-repeat-style "^4.0.0" + postcss-normalize-string "^4.0.0" + postcss-normalize-timing-functions "^4.0.0" + postcss-normalize-unicode "^4.0.0" + postcss-normalize-url "^4.0.0" + postcss-normalize-whitespace "^4.0.0" + postcss-ordered-values "^4.0.0" + postcss-reduce-initial "^4.0.0" + postcss-reduce-transforms "^4.0.0" + postcss-svgo "^4.0.0" + postcss-unique-selectors "^4.0.0" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + +cssnano-util-raw-cache@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.0.tgz#be0a2856e25f185f5f7a2bcc0624e28b7f179a9f" + dependencies: + postcss "^6.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.0.tgz#d2a3de1039aa98bc4ec25001fa050330c2a16dac" + +cssnano@^3.4.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-3.10.0.tgz#4f38f6cea2b9b17fa01490f23f1dc68ea65c1c38" + dependencies: + autoprefixer "^6.3.1" + decamelize "^1.1.2" + defined "^1.0.0" + has "^1.0.1" + object-assign "^4.0.1" + postcss "^5.0.14" + postcss-calc "^5.2.0" + postcss-colormin "^2.1.8" + postcss-convert-values "^2.3.4" + postcss-discard-comments "^2.0.4" + postcss-discard-duplicates "^2.0.1" + postcss-discard-empty "^2.0.1" + postcss-discard-overridden "^0.1.1" + postcss-discard-unused "^2.2.1" + postcss-filter-plugins "^2.0.0" + postcss-merge-idents "^2.1.5" + postcss-merge-longhand "^2.0.1" + postcss-merge-rules "^2.0.3" + postcss-minify-font-values "^1.0.2" + postcss-minify-gradients "^1.0.1" + postcss-minify-params "^1.0.4" + postcss-minify-selectors "^2.0.4" + postcss-normalize-charset "^1.1.0" + postcss-normalize-url "^3.0.7" + postcss-ordered-values "^2.1.0" + postcss-reduce-idents "^2.2.2" + postcss-reduce-initial "^1.0.0" + postcss-reduce-transforms "^1.0.3" + postcss-svgo "^2.1.1" + postcss-unique-selectors "^2.0.2" + postcss-value-parser "^3.2.3" + postcss-zindex "^2.0.1" + +cssnano@^4.0.0: + version "4.0.5" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.0.5.tgz#8789b5fdbe7be05d8a0f7e45c4c789ebe712f5aa" + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.0" + is-resolvable "^1.0.0" + postcss "^6.0.0" + +csso@^3.5.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" + dependencies: + css-tree "1.0.0-alpha.29" + +csso@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-2.3.2.tgz#ddd52c587033f49e94b71fc55569f252e8ff5f85" + dependencies: + clap "^1.0.9" + source-map "^0.5.3" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + +cyclist@~0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-0.2.2.tgz#1b33792e11e914a2fd6d6ed6447464444e5fa640" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +deasync@^0.1.13: + version "0.1.13" + resolved "https://registry.yarnpkg.com/deasync/-/deasync-0.1.13.tgz#815c2b69bbd1117cae570152cd895661c09f20ea" + dependencies: + bindings "~1.2.1" + nan "^2.0.7" + +debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + dependencies: + ms "2.0.0" + +debug@3.1.0, debug@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + dependencies: + ms "2.0.0" + +debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + +decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +defined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + +deps-sort@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" + dependencies: + JSONStream "^1.0.3" + shasum "^1.0.0" + subarg "^1.0.0" + through2 "^2.0.0" + +des.js@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-indent@~5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +detect-newline@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + +detective@^4.0.0: + version "4.7.1" + resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" + dependencies: + acorn "^5.2.1" + defined "^1.0.0" + +dezalgo@^1.0.0, dezalgo@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + dependencies: + asap "^2.0.0" + wrappy "1" + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + +domain-browser@~1.1.0: + version "1.1.7" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc" + +domelementtype@1, domelementtype@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + dependencies: + domelementtype "1" + +domready@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/domready/-/domready-1.0.8.tgz#91f252e597b65af77e745ae24dd0185d5e26d58c" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.0, dot-prop@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + +dotenv@^5.0.0, dotenv@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-5.0.1.tgz#a5317459bd3d79ab88cff6e44057a6a3fbb1fcef" + +duplexer2@^0.1.2, duplexer2@~0.1.0, duplexer2@~0.1.2, duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + dependencies: + readable-stream "^2.0.2" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +editor@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/editor/-/editor-1.0.0.tgz#60c7f87bd62bcc6a894fa8ccd6afb7823a24f742" + +editorconfig@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" + dependencies: + bluebird "^3.0.5" + commander "^2.9.0" + lru-cache "^3.2.0" + semver "^5.1.0" + sigmund "^1.0.1" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + +electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.47, electron-to-chromium@^1.3.52: + version "1.3.55" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.55.tgz#f150e10b20b77d9d41afcca312efe0c3b1a7fdce" + +elem-dataset@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/elem-dataset/-/elem-dataset-1.1.1.tgz#18f07fa7fc71ebd49b0f9f63819cb03c8276577a" + +element-closest@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/element-closest/-/element-closest-2.0.2.tgz#72a740a107453382e28df9ce5dbb5a8df0f966ec" + +elliptic@^6.0.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" + dependencies: + 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" + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" + dependencies: + once "^1.4.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +err-code@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" + +errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + dependencies: + prr "~1.0.1" + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.5.1, es-abstract@^1.6.1: + version "1.12.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.1" + has "^1.0.1" + is-callable "^1.1.3" + is-regex "^1.0.4" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +es6-promise@^4.0.3: + version "4.2.4" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + dependencies: + es6-promise "^4.0.3" + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escodegen@^1.8.1: + version "1.11.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.11.0.tgz#b27a9389481d5bfd5bec76f7bb1eb3f8f4556589" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +escodegen@~1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + +esprima@^2.6.0: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + +esprima@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + +estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + +events@^1.0.0, events@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.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" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + dependencies: + 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" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.0, extend@~3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + dependencies: + 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" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + +falafel@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.1.0.tgz#96bb17761daba94f46d001738b3cedf3a67fe06c" + dependencies: + acorn "^5.0.0" + foreach "^2.0.5" + isarray "0.0.1" + object-keys "^1.0.6" + +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + +fast-glob@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf" + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.0.1" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.1" + micromatch "^3.1.10" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +figgy-pudding@^3.0.0, figgy-pudding@^3.1.0, figgy-pudding@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.2.0.tgz#464626b73d7b0fc045a99753d191b0785957ff73" + +filesize@^3.6.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-npm-prefix@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flatten@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" + +flush-write-stream@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.0.3.tgz#c5d586ef38af6097650b49bc41b55fabb19f35bd" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.4" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + +from2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-1.3.0.tgz#88413baaa5f9a597cfde9221d86986cd3c061dfd" + dependencies: + inherits "~2.0.1" + readable-stream "~1.1.10" + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-minipass@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + dependencies: + minipass "^2.2.1" + +fs-vacuum@^1.2.10, fs-vacuum@~1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" + dependencies: + graceful-fs "^4.1.2" + path-is-inside "^1.0.1" + rimraf "^2.5.2" + +fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +fsevents@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.4.tgz#f41dcb1af2582af3692da36fc55cbd8e1041c426" + dependencies: + nan "^2.9.2" + node-pre-gyp "^0.10.0" + +fstream@^1.0.0, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +fswatcher-child@^1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fswatcher-child/-/fswatcher-child-1.0.5.tgz#134d012ffa74918975617e00e56e4139f36cb140" + dependencies: + chokidar "^2.0.3" + +function-bind@^1.1.0, function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + 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" + +gaze@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-1.1.3.tgz#c441733e13b927ac8c0ff0b4c3b033f28812924a" + dependencies: + globule "^1.0.0" + +genfun@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1" + +gentle-fs@^2.0.0, gentle-fs@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/gentle-fs/-/gentle-fs-2.0.1.tgz#585cfd612bfc5cd52471fdb42537f016a5ce3687" + dependencies: + aproba "^1.1.2" + fs-vacuum "^1.2.10" + graceful-fs "^4.1.11" + iferr "^0.1.5" + mkdirp "^0.5.1" + path-is-inside "^1.0.2" + read-cmd-shim "^1.0.1" + slide "^1.1.6" + +get-assigned-identifiers@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz#6dbf411de648cbaf8d9169ebb0d2d576191e2ff1" + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + +get-port@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + +glob@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + 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" + +global-dirs@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + dependencies: + ini "^1.3.4" + +globals@^9.18.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globule@^1.0.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/globule/-/globule-1.2.1.tgz#5dffb1b191f22d20797a9369b49eab4e9839696d" + dependencies: + glob "~7.1.1" + lodash "~4.17.10" + minimatch "~3.0.2" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@~4.1.11: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +grapheme-breaker@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/grapheme-breaker/-/grapheme-breaker-0.3.2.tgz#5b9e6b78c3832452d2ba2bb1cb830f96276410ac" + dependencies: + brfs "^1.2.0" + unicode-trie "^0.3.1" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" + +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + +has-unicode@^2.0.0, has-unicode@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.0, has@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.5" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: + version "2.7.1" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + +html-comment-regex@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e" + +htmlescape@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" + +htmlnano@^0.1.9: + version "0.1.9" + resolved "https://registry.yarnpkg.com/htmlnano/-/htmlnano-0.1.9.tgz#e6137aea84d20311a3875c42eb2799a1ff352627" + dependencies: + cssnano "^3.4.0" + object-assign "^4.0.1" + posthtml "^0.11.3" + posthtml-render "^1.1.3" + svgo "^1.0.5" + uglify-es "^3.3.9" + +htmlparser2@^3.9.2: + version "3.9.2" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" + dependencies: + domelementtype "^1.3.0" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^2.0.2" + +http-cache-semantics@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + dependencies: + agent-base "4" + debug "3.1.0" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + +https-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" + +https-proxy-agent@^2.2.0, https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + dependencies: + ms "^2.0.0" + +iconv-lite@^0.4.4, iconv-lite@~0.4.13: + version "0.4.23" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ieee754@^1.1.4: + version "1.1.12" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + +iferr@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-1.0.2.tgz#e9fde49a9da06dc4a4194c6c9ed6d08305037a6d" + +ignore-walk@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + dependencies: + minimatch "^3.0.4" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +in-publish@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/in-publish/-/in-publish-2.0.0.tgz#e20ff5e3a2afc2690320b6dc552682a9c7fadf51" + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + +inflight@^1.0.4, inflight@~1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + +init-package-json@^1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" + dependencies: + glob "^7.1.1" + npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" + promzard "^0.3.0" + read "~1.0.1" + read-package-json "1 || 2" + semver "2.x || 3.x || 4 || 5" + validate-npm-package-license "^3.0.1" + validate-npm-package-name "^3.0.0" + +inline-source-map@~0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" + dependencies: + source-map "~0.5.3" + +insert-module-globals@^7.0.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/insert-module-globals/-/insert-module-globals-7.2.0.tgz#ec87e5b42728479e327bd5c5c71611ddfb4752ba" + dependencies: + JSONStream "^1.0.3" + acorn-node "^1.5.2" + combine-source-map "^0.8.0" + concat-stream "^1.6.1" + is-buffer "^1.1.0" + path-is-absolute "^1.0.1" + process "~0.11.0" + through2 "^2.0.0" + undeclared-identifiers "^1.1.2" + xtend "^4.0.0" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + dependencies: + loose-envify "^1.0.0" + +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + +ip@^1.1.4, ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.0, is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + +is-ci@^1.0.10: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.1.0.tgz#247e4162e7860cebbdaf30b774d6b0ac7dcfe7a5" + dependencies: + ci-info "^1.0.0" + +is-cidr@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/is-cidr/-/is-cidr-2.0.6.tgz#4b01c9693d8e18399dacd18a4f3d60ea5871ac60" + dependencies: + cidr-regex "^2.0.8" + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + dependencies: + is-extglob "^2.1.1" + +is-installed-globally@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + dependencies: + global-dirs "^0.1.0" + is-path-inside "^1.0.0" + +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-path-inside@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" + dependencies: + path-is-inside "^1.0.1" + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-svg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-2.1.0.tgz#cf61090da0d9efbcab8722deba6f032208dbb0e9" + dependencies: + html-comment-regex "^1.1.0" + +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-url@^1.2.2: + version "1.2.4" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.4.tgz#04a4df46d28c4cff3d73d01ff06abeb318a1aa52" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isarray@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.4.tgz#38e7bcbb0f3ba1b7933c86ba1894ddfc3781bbb7" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0, isobject@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +js-base64@^2.1.8, js-base64@^2.1.9: + version "2.4.8" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.8.tgz#57a9b130888f956834aa40c5b165ba59c758f033" + +js-beautify@^1.7.5: + version "1.7.5" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.7.5.tgz#69d9651ef60dbb649f65527b53674950138a7919" + dependencies: + config-chain "~1.1.5" + editorconfig "^0.13.2" + mkdirp "~0.5.0" + nopt "~3.0.1" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.10.0, js-yaml@^3.9.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.12.0.tgz#eaed656ec8344f10f527c6bfa1b6e2244de167d1" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@~3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80" + dependencies: + argparse "^1.0.7" + esprima "^2.6.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json-stable-stringify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz#611c23e814db375527df851193db59dd2af27f45" + dependencies: + jsonify "~0.0.0" + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + +json5@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + dependencies: + minimist "^1.2.0" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +keyboardevent-key-polyfill@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/keyboardevent-key-polyfill/-/keyboardevent-key-polyfill-1.1.0.tgz#8a319d8e45a13172fca56286372f90c1d4c7014c" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + +labeled-stream-splicer@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz#9cffa32fd99e1612fd1d86a8db962416d5292926" + dependencies: + inherits "^2.0.1" + isarray "^2.0.4" + stream-splicer "^2.0.0" + +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + dependencies: + package-json "^4.0.0" + +lazy-property@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lazy-property/-/lazy-property-1.0.0.tgz#84ddc4b370679ba8bd4cdcfa4c06b43d57111147" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +libcipm@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/libcipm/-/libcipm-2.0.1.tgz#2f4ebf8562e0fc6e46f415373674e4cf3ac4b9ba" + dependencies: + bin-links "^1.1.2" + bluebird "^3.5.1" + find-npm-prefix "^1.0.2" + graceful-fs "^4.1.11" + lock-verify "^2.0.2" + mkdirp "^0.5.1" + npm-lifecycle "^2.0.3" + npm-logical-tree "^1.2.1" + npm-package-arg "^6.1.0" + pacote "^8.1.6" + protoduck "^5.0.0" + read-package-json "^2.0.13" + rimraf "^2.6.2" + worker-farm "^1.6.0" + +libnpmhook@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-4.0.1.tgz#63641654de772cbeb96a88527a7fd5456ec3c2d7" + dependencies: + figgy-pudding "^3.1.0" + npm-registry-fetch "^3.0.0" + +libnpx@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/libnpx/-/libnpx-10.2.0.tgz#1bf4a1c9f36081f64935eb014041da10855e3102" + dependencies: + dotenv "^5.0.1" + npm-package-arg "^6.0.0" + rimraf "^2.6.2" + safe-buffer "^5.1.0" + update-notifier "^2.3.0" + which "^1.3.0" + y18n "^4.0.0" + yargs "^11.0.0" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lock-verify@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lock-verify/-/lock-verify-2.0.2.tgz#148e4f85974915c9e3c34d694b7de9ecb18ee7a8" + dependencies: + npm-package-arg "^5.1.2 || 6" + semver "^5.4.1" + +lockfile@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lockfile/-/lockfile-1.0.4.tgz#07f819d25ae48f87e538e6578b6964a4981a5609" + dependencies: + signal-exit "^3.0.2" + +lodash._baseuniq@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" + dependencies: + lodash._createset "~4.0.0" + lodash._root "~3.0.0" + +lodash._createset@~4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" + +lodash._root@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + +lodash.assign@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" + +lodash.clone@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clone/-/lodash.clone-4.5.0.tgz#195870450f5a13192478df4bc3d23d2dea1907b6" + +lodash.clonedeep@^4.3.2, lodash.clonedeep@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + +lodash.debounce@^4.0.7, lodash.debounce@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + +lodash.memoize@~3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" + +lodash.mergewith@^4.6.0: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927" + +lodash.union@~4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" + +lodash.uniq@^4.5.0, lodash.uniq@~4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + +lodash.without@~4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" + +lodash@^4.0.0, lodash@^4.17.4, lodash@~4.17.10: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + +log-symbols@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + dependencies: + chalk "^2.0.1" + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lowercase-keys@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + dependencies: + pseudomap "^1.0.1" + +lru-cache@^4.0.1, lru-cache@^4.1.1, lru-cache@^4.1.2, lru-cache@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +magic-string@^0.22.4: + version "0.22.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.5.tgz#8e9cf5afddf44385c1da5bc2a6a0dbd10b03657e" + dependencies: + vlq "^0.2.2" + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + dependencies: + pify "^3.0.0" + +"make-fetch-happen@^2.5.0 || 3 || 4", make-fetch-happen@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-4.0.1.tgz#141497cb878f243ba93136c83d8aba12c216c083" + dependencies: + agentkeepalive "^3.4.1" + cacache "^11.0.1" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.1" + lru-cache "^4.1.2" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^4.0.0" + ssri "^6.0.0" + +make-fetch-happen@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-3.0.0.tgz#7b661d2372fc4710ab5cc8e1fa3c290eea69a961" + dependencies: + agentkeepalive "^3.4.1" + cacache "^10.0.4" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.0" + lru-cache "^4.1.2" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^3.0.1" + ssri "^5.2.4" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + dependencies: + object-visit "^1.0.0" + +matches-selector@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/matches-selector/-/matches-selector-1.2.0.tgz#d1814e7e8f43e69d22ac33c9af727dc884ecf12a" + +math-expression-evaluator@^1.2.14: + version "1.2.17" + resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac" + +md5.js@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +mdn-data@^1.0.0, mdn-data@~1.1.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" + +meant@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/meant/-/meant-1.0.1.tgz#66044fea2f23230ec806fb515efea29c44d2115d" + +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + +meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +merge-source-map@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" + dependencies: + source-map "^0.5.6" + +merge2@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.2.tgz#03212e3da8d86c4d8523cebd6318193414f94e34" + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@~1.35.0: + version "1.35.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: + version "2.1.19" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.19.tgz#71e464537a7ef81c15f2db9d97e913fc0ff606f0" + dependencies: + mime-db "~1.35.0" + +mime@1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + +"minimatch@2 || 3", minimatch@^3.0.2, minimatch@^3.0.4, minimatch@~3.0.2: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0, minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +minipass@^2.2.1, minipass@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.0.tgz#11e13658ce46bc3a70a267aac58359d1e0c29ceb" + dependencies: + minipass "^2.2.1" + +mississippi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-2.0.0.tgz#3442a508fafc28500486feea99409676e4ee5a6f" + dependencies: + 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 "^2.0.1" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + dependencies: + 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" + +mixin-deep@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +module-deps@^4.0.8: + version "4.1.1" + resolved "https://registry.yarnpkg.com/module-deps/-/module-deps-4.1.1.tgz#23215833f1da13fd606ccb8087b44852dcb821fd" + dependencies: + JSONStream "^1.0.3" + browser-resolve "^1.7.0" + cached-path-relative "^1.0.0" + concat-stream "~1.5.0" + defined "^1.0.0" + detective "^4.0.0" + duplexer2 "^0.1.2" + inherits "^2.0.1" + parents "^1.0.0" + readable-stream "^2.0.2" + resolve "^1.1.3" + stream-combiner2 "^1.1.1" + subarg "^1.0.0" + through2 "^2.0.0" + xtend "^4.0.0" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +ms@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + +mute-stream@~0.0.4: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +nan@^2.0.7, nan@^2.10.0, nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.1.tgz#b5e325bd3aae8c2678902fa296f729455d1d3a7d" + dependencies: + debug "^2.1.2" + iconv-lite "^0.4.4" + sax "^1.2.4" + +nice-try@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.4.tgz#d93962f6c52f2c1558c0fbda6d512819f1efe1c4" + +node-fetch-npm@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" + dependencies: + encoding "^0.1.11" + json-parse-better-errors "^1.0.0" + safe-buffer "^5.1.1" + +node-forge@^0.7.1: + version "0.7.5" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" + +node-gyp@^3.3.1, node-gyp@^3.6.2, node-gyp@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.7.0.tgz#789478e8f6c45e277aa014f3e28f958f286f9203" + dependencies: + fstream "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request ">=2.9.0 <2.82.0" + rimraf "2" + semver "~5.3.0" + tar "^2.0.0" + which "1" + +node-libs-browser@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.1.0.tgz#5f94263d404f6e44767d726901fff05478d600df" + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^1.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.0" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.10.3" + vm-browserify "0.0.4" + +node-pre-gyp@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + dependencies: + 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" + +node-releases@^1.0.0-alpha.10: + version "1.0.0-alpha.10" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.0.0-alpha.10.tgz#61c8d5f9b5b2e05d84eba941d05b6f5202f68a2a" + dependencies: + semver "^5.3.0" + +node-sass@^4.9.2: + version "4.9.2" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.9.2.tgz#5e63fe6bd0f2ae3ac9d6c14ede8620e2b8bdb437" + dependencies: + async-foreach "^0.1.3" + chalk "^1.1.1" + cross-spawn "^3.0.0" + gaze "^1.0.0" + get-stdin "^4.0.1" + glob "^7.0.3" + in-publish "^2.0.0" + lodash.assign "^4.2.0" + lodash.clonedeep "^4.3.2" + lodash.mergewith "^4.6.0" + meow "^3.7.0" + mkdirp "^0.5.1" + nan "^2.10.0" + node-gyp "^3.3.1" + npmlog "^4.0.0" + request "2.87.0" + sass-graph "^2.2.4" + stdout-stream "^1.4.0" + "true-case-path" "^1.0.2" + +"nopt@2 || 3", nopt@~3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + dependencies: + abbrev "1" + +nopt@^4.0.1, nopt@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, "normalize-package-data@~1.0.1 || ^2.0.0", normalize-package-data@~2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + +normalize-url@^1.4.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + dependencies: + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +normalize-url@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.2.0.tgz#98d0948afc82829f374320f405fe9ca55a5f8567" + +npm-audit-report@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-1.3.1.tgz#e79ea1fcb5ffaf3031102b389d5222c2b0459632" + dependencies: + cli-table3 "^0.5.0" + console-control-strings "^1.1.0" + +npm-bundled@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.3.tgz#7e71703d973af3370a9591bafe3a63aca0be2308" + +npm-cache-filename@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/npm-cache-filename/-/npm-cache-filename-1.0.2.tgz#ded306c5b0bfc870a9e9faf823bc5f283e05ae11" + +npm-install-checks@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-3.0.0.tgz#d4aecdfd51a53e3723b7b2f93b2ee28e307bc0d7" + dependencies: + semver "^2.3.0 || 3.x || 4 || 5" + +npm-lifecycle@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-2.0.3.tgz#696bedf1143371163e9cc16fe872357e25d8d90e" + dependencies: + byline "^5.0.0" + graceful-fs "^4.1.11" + node-gyp "^3.6.2" + resolve-from "^4.0.0" + slide "^1.1.6" + uid-number "0.0.6" + umask "^1.1.0" + which "^1.3.0" + +npm-logical-tree@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/npm-logical-tree/-/npm-logical-tree-1.2.1.tgz#44610141ca24664cad35d1e607176193fd8f5b88" + +"npm-package-arg@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0", "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", "npm-package-arg@^5.1.2 || 6", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.0.tgz#15ae1e2758a5027efb4c250554b85a737db7fcc1" + dependencies: + hosted-git-info "^2.6.0" + osenv "^0.1.5" + semver "^5.5.0" + validate-npm-package-name "^3.0.0" + +npm-packlist@^1.1.10, npm-packlist@^1.1.6, npm-packlist@~1.1.10: + version "1.1.11" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.11.tgz#84e8c683cbe7867d34b1d357d893ce29e28a02de" + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-pick-manifest@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-2.1.0.tgz#dc381bdd670c35d81655e1d5a94aa3dd4d87fce5" + dependencies: + npm-package-arg "^6.0.0" + semver "^5.4.1" + +npm-profile@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-3.0.2.tgz#58d568f1b56ef769602fd0aed8c43fa0e0de0f57" + dependencies: + aproba "^1.1.2 || 2" + make-fetch-happen "^2.5.0 || 3 || 4" + +npm-registry-client@^8.5.1: + version "8.6.0" + resolved "https://registry.yarnpkg.com/npm-registry-client/-/npm-registry-client-8.6.0.tgz#7f1529f91450732e89f8518e0f21459deea3e4c4" + dependencies: + concat-stream "^1.5.2" + graceful-fs "^4.1.6" + normalize-package-data "~1.0.1 || ^2.0.0" + npm-package-arg "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + once "^1.3.3" + request "^2.74.0" + retry "^0.10.0" + safe-buffer "^5.1.1" + semver "2 >=2.2.1 || 3.x || 4 || 5" + slide "^1.1.3" + ssri "^5.2.4" + optionalDependencies: + npmlog "2 || ^3.1.0 || ^4.0.0" + +npm-registry-fetch@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-1.1.1.tgz#710bc5947d9ee2c549375072dab6d5d17baf2eb2" + dependencies: + bluebird "^3.5.1" + figgy-pudding "^3.0.0" + lru-cache "^4.1.2" + make-fetch-happen "^3.0.0" + npm-package-arg "^6.0.0" + safe-buffer "^5.1.1" + +npm-registry-fetch@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-3.2.0.tgz#94ec859c4dd395f924e575cee471da6fd3906d53" + dependencies: + bluebird "^3.5.1" + figgy-pudding "^3.2.0" + lru-cache "^4.1.3" + make-fetch-happen "^4.0.1" + npm-package-arg "^6.1.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npm-user-validate@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/npm-user-validate/-/npm-user-validate-1.0.0.tgz#8ceca0f5cea04d4e93519ef72d0557a75122e951" + +npm@^6.0.1: + version "6.3.0" + resolved "https://registry.yarnpkg.com/npm/-/npm-6.3.0.tgz#de7df51f6d1b05b088486097cf7993dbbcac752f" + dependencies: + JSONStream "^1.3.3" + abbrev "~1.1.1" + ansicolors "~0.3.2" + ansistyles "~0.1.3" + aproba "~1.2.0" + archy "~1.0.0" + bin-links "^1.1.2" + bluebird "~3.5.1" + byte-size "^4.0.3" + cacache "^11.1.0" + call-limit "~1.1.0" + chownr "~1.0.1" + cli-columns "^3.1.2" + cli-table3 "^0.5.0" + cmd-shim "~2.0.2" + columnify "~1.5.4" + config-chain "~1.1.11" + detect-indent "~5.0.0" + detect-newline "^2.1.0" + dezalgo "~1.0.3" + editor "~1.0.0" + figgy-pudding "^3.2.0" + find-npm-prefix "^1.0.2" + fs-vacuum "~1.2.10" + fs-write-stream-atomic "~1.0.10" + gentle-fs "^2.0.1" + glob "~7.1.2" + graceful-fs "~4.1.11" + has-unicode "~2.0.1" + hosted-git-info "^2.6.0" + iferr "^1.0.0" + inflight "~1.0.6" + inherits "~2.0.3" + ini "^1.3.5" + init-package-json "^1.10.3" + is-cidr "^2.0.6" + json-parse-better-errors "^1.0.2" + lazy-property "~1.0.0" + libcipm "^2.0.0" + libnpmhook "^4.0.1" + libnpx "^10.2.0" + lock-verify "^2.0.2" + lockfile "^1.0.4" + lodash._baseuniq "~4.6.0" + lodash.clonedeep "~4.5.0" + lodash.union "~4.6.0" + lodash.uniq "~4.5.0" + lodash.without "~4.4.0" + lru-cache "^4.1.3" + meant "~1.0.1" + mississippi "^3.0.0" + mkdirp "~0.5.1" + move-concurrently "^1.0.1" + node-gyp "^3.7.0" + nopt "~4.0.1" + normalize-package-data "~2.4.0" + npm-audit-report "^1.3.1" + npm-cache-filename "~1.0.2" + npm-install-checks "~3.0.0" + npm-lifecycle "^2.0.3" + npm-package-arg "^6.1.0" + npm-packlist "~1.1.10" + npm-pick-manifest "^2.1.0" + npm-profile "^3.0.2" + npm-registry-client "^8.5.1" + npm-registry-fetch "^1.1.0" + npm-user-validate "~1.0.0" + npmlog "~4.1.2" + once "~1.4.0" + opener "~1.4.3" + osenv "^0.1.5" + pacote "^8.1.6" + path-is-inside "~1.0.2" + promise-inflight "~1.0.1" + qrcode-terminal "^0.12.0" + query-string "^6.1.0" + qw "~1.0.1" + read "~1.0.7" + read-cmd-shim "~1.0.1" + read-installed "~4.0.3" + read-package-json "^2.0.13" + read-package-tree "^5.2.1" + readable-stream "^2.3.6" + request "^2.81.0" + retry "^0.12.0" + rimraf "~2.6.2" + safe-buffer "^5.1.2" + semver "^5.5.0" + sha "~2.0.1" + slide "~1.1.6" + sorted-object "~2.0.1" + sorted-union-stream "~2.1.3" + ssri "^6.0.0" + stringify-package "^1.0.0" + tar "^4.4.4" + text-table "~0.2.0" + tiny-relative-date "^1.3.0" + uid-number "0.0.6" + umask "~1.1.0" + unique-filename "~1.1.0" + unpipe "~1.0.0" + update-notifier "^2.5.0" + uuid "^3.3.2" + validate-npm-package-license "^3.0.3" + validate-npm-package-name "~3.0.0" + which "^1.3.1" + worker-farm "^1.6.0" + write-file-atomic "^2.3.0" + +"npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@~4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nth-check@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.1.tgz#9929acdf628fc2c41098deab82ac580cf149aae4" + dependencies: + boolbase "~1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +oauth-sign@~0.8.1, oauth-sign@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@~1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.4.1.tgz#37ffb10e71adaf3748d05f713b4c9452f402cbc4" + +object-keys@^1.0.6, object-keys@^1.0.8: + version "1.0.12" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + dependencies: + isobject "^3.0.0" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + dependencies: + isobject "^3.0.1" + +object.values@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.0.4.tgz#e524da09b4f66ff05df457546ec72ac99f13069a" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.6.1" + function-bind "^1.1.0" + has "^1.0.1" + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + dependencies: + ee-first "1.1.1" + +once@^1.3.0, once@^1.3.1, once@^1.3.3, once@^1.4.0, once@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +opener@~1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.4.3.tgz#5c6da2c5d7e5831e8ffa3964950f8d6674ac90b8" + +opn@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" + dependencies: + is-wsl "^1.1.0" + +optionator@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +ora@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-2.1.0.tgz#6caf2830eb924941861ec53a173799e008b51e5b" + dependencies: + chalk "^2.3.1" + cli-cursor "^2.1.0" + cli-spinners "^1.1.0" + log-symbols "^2.2.0" + strip-ansi "^4.0.0" + wcwidth "^1.0.1" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + +os-browserify@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.1.2.tgz#49ca0293e0b19590a5f5de10c7f265a617d8fe54" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +os-locale@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" + dependencies: + execa "^0.7.0" + lcid "^1.0.0" + mem "^1.1.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +osenv@0, osenv@^0.1.4, osenv@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + dependencies: + p-try "^1.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +pacote@^8.1.6: + version "8.1.6" + resolved "https://registry.yarnpkg.com/pacote/-/pacote-8.1.6.tgz#8e647564d38156367e7a9dc47a79ca1ab278d46e" + dependencies: + bluebird "^3.5.1" + cacache "^11.0.2" + get-stream "^3.0.0" + glob "^7.1.2" + lru-cache "^4.1.3" + make-fetch-happen "^4.0.1" + minimatch "^3.0.4" + minipass "^2.3.3" + mississippi "^3.0.0" + mkdirp "^0.5.1" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + npm-packlist "^1.1.10" + npm-pick-manifest "^2.1.0" + osenv "^0.1.5" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^5.0.0" + rimraf "^2.6.2" + safe-buffer "^5.1.2" + semver "^5.5.0" + ssri "^6.0.0" + tar "^4.4.3" + unique-filename "^1.1.0" + which "^1.3.0" + +pako@^0.2.5, pako@~0.2.0: + version "0.2.9" + resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" + +pako@~1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258" + +parallel-transform@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.1.0.tgz#d410f065b05da23081fcd10f28854c29bda33b06" + dependencies: + cyclist "~0.2.2" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parcel@^1.9.7: + version "1.9.7" + resolved "https://registry.yarnpkg.com/parcel/-/parcel-1.9.7.tgz#77ca0cdb305d8e9365ded4762ee39ca760b0c219" + dependencies: + ansi-to-html "^0.6.4" + babel-code-frame "^6.26.0" + babel-core "^6.25.0" + babel-generator "^6.25.0" + babel-plugin-transform-es2015-modules-commonjs "^6.26.0" + babel-plugin-transform-react-jsx "^6.24.1" + babel-preset-env "^1.7.0" + babel-template "^6.26.0" + babel-traverse "^6.26.0" + babel-types "^6.26.0" + babylon "^6.17.4" + babylon-walk "^1.0.2" + browserslist "^3.2.6" + chalk "^2.1.0" + clone "^2.1.1" + command-exists "^1.2.6" + commander "^2.11.0" + cross-spawn "^6.0.4" + cssnano "^4.0.0" + deasync "^0.1.13" + dotenv "^5.0.0" + fast-glob "^2.2.2" + filesize "^3.6.0" + fswatcher-child "^1.0.3" + get-port "^3.2.0" + grapheme-breaker "^0.3.2" + htmlnano "^0.1.9" + is-glob "^4.0.0" + is-url "^1.2.2" + js-yaml "^3.10.0" + json5 "^1.0.1" + micromatch "^3.0.4" + mkdirp "^0.5.1" + node-forge "^0.7.1" + node-libs-browser "^2.0.0" + opn "^5.1.0" + ora "^2.1.0" + physical-cpu-count "^2.0.0" + postcss "^6.0.19" + postcss-value-parser "^3.3.0" + posthtml "^0.11.2" + posthtml-parser "^0.4.0" + posthtml-render "^1.1.3" + resolve "^1.4.0" + semver "^5.4.1" + serialize-to-js "^1.1.1" + serve-static "^1.12.4" + source-map "0.6.1" + strip-ansi "^4.0.0" + terser "^3.7.3" + toml "^2.3.3" + tomlify-j0.4 "^3.0.0" + v8-compile-cache "^2.0.0" + ws "^5.1.1" + +parents@^1.0.0, parents@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parents/-/parents-1.0.1.tgz#fedd4d2bf193a77745fe71e371d73c3307d9c751" + dependencies: + path-platform "~0.11.15" + +parse-asn1@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.1.tgz#f6bf293818332bd0dab54efb16087724745e6ca8" + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parseurl@~1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + +path-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.0.tgz#a0b870729aae214005b7d5032ec2cbbb0fb4451a" + +path-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-platform@~0.11.15: + version "0.11.15" + resolved "https://registry.yarnpkg.com/path-platform/-/path-platform-0.11.15.tgz#e864217f74c36850f0852b78dc7bf7d4a5721bf2" + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pbkdf2@^3.0.3: + version "3.0.16" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + +physical-cpu-count@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/physical-cpu-count/-/physical-cpu-count-2.0.0.tgz#18de2f97e4bf7a9551ad7511942b5496f7aba660" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + +postcss-calc@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" + dependencies: + postcss "^5.0.2" + postcss-message-helpers "^2.0.0" + reduce-css-calc "^1.2.6" + +postcss-calc@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-6.0.1.tgz#3d24171bbf6e7629d422a436ebfe6dd9511f4330" + dependencies: + css-unit-converter "^1.1.1" + postcss "^6.0.0" + postcss-selector-parser "^2.2.2" + reduce-css-calc "^2.0.0" + +postcss-colormin@^2.1.8: + version "2.2.2" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-2.2.2.tgz#6631417d5f0e909a3d7ec26b24c8a8d1e4f96e4b" + dependencies: + colormin "^1.0.5" + postcss "^5.0.13" + postcss-value-parser "^3.2.3" + +postcss-colormin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.1.tgz#6f1c18a0155bc69613f2ff13843e2e4ae8ff0bbe" + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^2.3.4: + version "2.6.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz#bbd8593c5c1fd2e3d1c322bb925dcae8dae4d62d" + dependencies: + postcss "^5.0.11" + postcss-value-parser "^3.1.2" + +postcss-convert-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.0.tgz#77d77d9aed1dc4e6956e651cc349d53305876f62" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-discard-comments@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz#befe89fafd5b3dace5ccce51b76b81514be00e3d" + dependencies: + postcss "^5.0.14" + +postcss-discard-comments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.0.tgz#9684a299e76b3e93263ef8fd2adbf1a1c08fd88d" + dependencies: + postcss "^6.0.0" + +postcss-discard-duplicates@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz#b9abf27b88ac188158a5eb12abcae20263b91932" + dependencies: + postcss "^5.0.4" + +postcss-discard-duplicates@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.0.tgz#42f3c267f85fa909e042c35767ecfd65cb2bd72c" + dependencies: + postcss "^6.0.0" + +postcss-discard-empty@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz#d2b4bd9d5ced5ebd8dcade7640c7d7cd7f4f92b5" + dependencies: + postcss "^5.0.14" + +postcss-discard-empty@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.0.tgz#55e18a59c74128e38c7d2804bcfa4056611fb97f" + dependencies: + postcss "^6.0.0" + +postcss-discard-overridden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz#8b1eaf554f686fb288cd874c55667b0aa3668d58" + dependencies: + postcss "^5.0.16" + +postcss-discard-overridden@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.0.tgz#4a0bf85978784cf1f81ed2c1c1fd9d964a1da1fa" + dependencies: + postcss "^6.0.0" + +postcss-discard-unused@^2.2.1: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz#bce30b2cc591ffc634322b5fb3464b6d934f4433" + dependencies: + postcss "^5.0.14" + uniqs "^2.0.0" + +postcss-filter-plugins@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/postcss-filter-plugins/-/postcss-filter-plugins-2.0.3.tgz#82245fdf82337041645e477114d8e593aa18b8ec" + dependencies: + postcss "^5.0.4" + +postcss-merge-idents@^2.1.5: + version "2.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz#4c5530313c08e1d5b3bbf3d2bbc747e278eea270" + dependencies: + has "^1.0.1" + postcss "^5.0.10" + postcss-value-parser "^3.1.1" + +postcss-merge-longhand@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz#23d90cd127b0a77994915332739034a1a4f3d658" + dependencies: + postcss "^5.0.4" + +postcss-merge-longhand@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.4.tgz#bffc7c6ffa146591c993a0bb8373d65f9a06d4d0" + dependencies: + css-color-names "0.0.4" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz#d1df5dfaa7b1acc3be553f0e9e10e87c61b5f721" + dependencies: + browserslist "^1.5.2" + caniuse-api "^1.5.2" + postcss "^5.0.4" + postcss-selector-parser "^2.2.2" + vendors "^1.0.0" + +postcss-merge-rules@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.1.tgz#430fd59b3f2ed2e8afcd0b31278eda39854abb10" + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^6.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-message-helpers@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" + +postcss-minify-font-values@^1.0.2: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz#4b58edb56641eba7c8474ab3526cafd7bbdecb69" + dependencies: + object-assign "^4.0.1" + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-minify-font-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.0.tgz#4cc33d283d6a81759036e757ef981d92cbd85bed" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz#5dbda11373703f83cfb4a3ea3881d8d75ff5e6e1" + dependencies: + postcss "^5.0.12" + postcss-value-parser "^3.3.0" + +postcss-minify-gradients@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.0.tgz#3fc3916439d27a9bb8066db7cdad801650eb090e" + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^1.0.4: + version "1.2.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz#ad2ce071373b943b3d930a3fa59a358c28d6f1f3" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.2" + postcss-value-parser "^3.0.2" + uniqs "^2.0.0" + +postcss-minify-params@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.0.tgz#05e9166ee48c05af651989ce84d39c1b4d790674" + dependencies: + alphanum-sort "^1.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^2.0.4: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz#b2c6a98c0072cf91b932d1a496508114311735bf" + dependencies: + alphanum-sort "^1.0.2" + has "^1.0.1" + postcss "^5.0.14" + postcss-selector-parser "^2.0.0" + +postcss-minify-selectors@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.0.tgz#b1e9f6c463416d3fcdcb26e7b785d95f61578aad" + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-selector-parser "^3.0.0" + +postcss-normalize-charset@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz#ef9ee71212d7fe759c78ed162f61ed62b5cb93f1" + dependencies: + postcss "^5.0.5" + +postcss-normalize-charset@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.0.tgz#24527292702d5e8129eafa3d1de49ed51a6ab730" + dependencies: + postcss "^6.0.0" + +postcss-normalize-display-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.0.tgz#950e0c7be3445770a160fffd6b6644c3c0cd8f89" + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.0.tgz#ee9343ab981b822c63ab72615ecccd08564445a3" + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.0.tgz#b711c592cf16faf9ff575e42fa100b6799083eff" + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.0.tgz#718cb6d30a6fac6ac6a830e32c06c07dbc66fe5d" + dependencies: + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.0.tgz#0351f29886aa981d43d91b2c2bd1aea6d0af6d23" + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.0.tgz#5acd5d47baea5d17674b2ccc4ae5166fa88cdf97" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^3.0.7: + version "3.0.8" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz#108f74b3f2fcdaf891a2ffa3ea4592279fc78222" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^1.4.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + +postcss-normalize-url@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.0.tgz#b7a9c8ad26cf26694c146eb2d68bd0cf49956f0d" + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.0.tgz#1da7e76b10ae63c11827fa04fc3bb4a1efe99cc0" + dependencies: + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz#eec6c2a67b6c412a8db2042e77fe8da43f95c11d" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.1" + +postcss-ordered-values@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.0.0.tgz#58b40c74f72e022eb34152c12e4b0f9354482fc2" + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-reduce-idents@^2.2.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz#c2c6d20cc958284f6abfbe63f7609bf409059ad3" + dependencies: + postcss "^5.0.4" + postcss-value-parser "^3.0.2" + +postcss-reduce-initial@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz#68f80695f045d08263a879ad240df8dd64f644ea" + dependencies: + postcss "^5.0.4" + +postcss-reduce-initial@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.1.tgz#f2d58f50cea2b0c5dc1278d6ea5ed0ff5829c293" + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^6.0.0" + +postcss-reduce-transforms@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz#ff76f4d8212437b31c298a42d2e1444025771ae1" + dependencies: + has "^1.0.1" + postcss "^5.0.8" + postcss-value-parser "^3.0.1" + +postcss-reduce-transforms@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.0.tgz#f645fc7440c35274f40de8104e14ad7163edf188" + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + +postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz#f9437788606c3c9acee16ffe8d8b16297f27bb90" + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^2.1.1: + version "2.1.6" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" + dependencies: + is-svg "^2.0.0" + postcss "^5.0.14" + postcss-value-parser "^3.2.3" + svgo "^0.7.0" + +postcss-svgo@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.0.tgz#c0bbad02520fc636c9d78b0e8403e2e515c32285" + dependencies: + is-svg "^3.0.0" + postcss "^6.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz#981d57d29ddcb33e7b1dfe1fd43b8649f933ca1d" + dependencies: + alphanum-sort "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss-unique-selectors@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.0.tgz#04c1e9764c75874261303402c41f0e9769fc5501" + dependencies: + alphanum-sort "^1.0.0" + postcss "^6.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.0.1, postcss-value-parser@^3.0.2, postcss-value-parser@^3.1.1, postcss-value-parser@^3.1.2, postcss-value-parser@^3.2.3, postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +postcss-zindex@^2.0.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-2.2.0.tgz#d2109ddc055b91af67fc4cb3b025946639d2af22" + dependencies: + has "^1.0.1" + postcss "^5.0.4" + uniqs "^2.0.0" + +postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0.14, postcss@^5.0.16, postcss@^5.0.2, postcss@^5.0.4, postcss@^5.0.5, postcss@^5.0.8, postcss@^5.2.16: + version "5.2.18" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.18.tgz#badfa1497d46244f6390f58b319830d9107853c5" + dependencies: + chalk "^1.1.3" + js-base64 "^2.1.9" + source-map "^0.5.6" + supports-color "^3.2.3" + +postcss@^6.0.0, postcss@^6.0.19: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + +posthtml-parser@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.3.3.tgz#3fe986fca9f00c0f109d731ba590b192f26e776d" + dependencies: + htmlparser2 "^3.9.2" + isobject "^2.1.0" + object-assign "^4.1.1" + +posthtml-parser@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/posthtml-parser/-/posthtml-parser-0.4.1.tgz#95b78fef766fbbe0a6f861b6e95582bc3d1ff933" + dependencies: + htmlparser2 "^3.9.2" + object-assign "^4.1.1" + +posthtml-render@^1.1.0, posthtml-render@^1.1.3: + version "1.1.4" + resolved "https://registry.yarnpkg.com/posthtml-render/-/posthtml-render-1.1.4.tgz#95dac09892f4f183fad5ac823f08f42c0256551e" + +posthtml@^0.11.2, posthtml@^0.11.3: + version "0.11.3" + resolved "https://registry.yarnpkg.com/posthtml/-/posthtml-0.11.3.tgz#17ea2921b0555b7455f33c977bd16d8b8cb74f27" + dependencies: + object-assign "^4.1.1" + posthtml-parser "^0.3.3" + posthtml-render "^1.1.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +prepend-http@^1.0.0, prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +private@^0.1.6, private@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +process-nextick-args@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" + +process@^0.11.10, process@~0.11.0: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + +promise-inflight@^1.0.1, promise-inflight@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + +promise-retry@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" + dependencies: + err-code "^1.0.0" + retry "^0.10.0" + +promzard@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" + dependencies: + read "1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + +protoduck@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.0.tgz#752145e6be0ad834cb25716f670a713c860dce70" + dependencies: + genfun "^4.0.1" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + +pseudomap@^1.0.1, pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +public-encrypt@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.2.tgz#46eb9107206bf73489f8b85b69d91334c6610994" + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + +pump@^2.0.0, pump@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + +punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + +qrcode-terminal@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +qs@~6.5.1: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +query-string@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.1.0.tgz#01e7d69f6a0940dac67a937d6c6325647aa4532a" + dependencies: + decode-uri-component "^0.2.0" + strict-uri-encode "^2.0.0" + +querystring-es3@^0.2.0, querystring-es3@~0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + +quote-stream@^1.0.1, quote-stream@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/quote-stream/-/quote-stream-1.0.2.tgz#84963f8c9c26b942e153feeb53aae74652b7e0b2" + dependencies: + buffer-equal "0.0.1" + minimist "^1.1.3" + through2 "^2.0.0" + +qw@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/qw/-/qw-1.0.1.tgz#efbfdc740f9ad054304426acb183412cc8b996d4" + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.0.6" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + +rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-cmd-shim@^1.0.1, read-cmd-shim@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.1.tgz#2d5d157786a37c055d22077c32c53f8329e91c7b" + dependencies: + graceful-fs "^4.1.2" + +read-installed@~4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/read-installed/-/read-installed-4.0.3.tgz#ff9b8b67f187d1e4c29b9feb31f6b223acd19067" + dependencies: + debuglog "^1.0.1" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + semver "2 || 3 || 4 || 5" + slide "~1.1.3" + util-extend "^1.0.1" + optionalDependencies: + graceful-fs "^4.1.2" + +read-only-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-only-stream/-/read-only-stream-2.0.0.tgz#2724fd6a8113d73764ac288d4386270c1dbf17f0" + dependencies: + readable-stream "^2.0.2" + +"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: + version "2.0.13" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.0.13.tgz#2e82ebd9f613baa6d2ebe3aa72cefe3f68e41f4a" + dependencies: + glob "^7.1.1" + json-parse-better-errors "^1.0.1" + normalize-package-data "^2.0.0" + slash "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-tree@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.2.1.tgz#6218b187d6fac82289ce4387bbbaf8eef536ad63" + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + once "^1.3.0" + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read@1, read@~1.0.1, read@~1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + dependencies: + mute-stream "~0.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.3: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + dependencies: + 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" + +readable-stream@~1.1.10: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@~2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e" + dependencies: + 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" + +readdir-scoped-modules@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747" + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + +receptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/receptor/-/receptor-1.0.0.tgz#bf54477e0387e44bebf3855120bbda5adea08f8b" + dependencies: + element-closest "^2.0.1" + keyboardevent-key-polyfill "^1.0.2" + matches-selector "^1.0.0" + object-assign "^4.1.0" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +reduce-css-calc@^1.2.6: + version "1.3.0" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz#747c914e049614a4c9cfbba629871ad1d2927716" + dependencies: + balanced-match "^0.4.2" + math-expression-evaluator "^1.2.14" + reduce-function-call "^1.0.1" + +reduce-css-calc@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/reduce-css-calc/-/reduce-css-calc-2.1.4.tgz#c20e9cda8445ad73d4ff4bea960c6f8353791708" + dependencies: + css-unit-converter "^1.1.1" + postcss-value-parser "^3.3.0" + +reduce-function-call@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reduce-function-call/-/reduce-function-call-1.0.2.tgz#5a200bf92e0e37751752fe45b0ab330fd4b6be99" + dependencies: + balanced-match "^0.4.2" + +regenerate@^1.2.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + +regenerator-transform@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +registry-auth-token@^3.0.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + dependencies: + rc "^1.0.1" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +request@2.87.0, request@^2.74.0, request@^2.81.0: + version "2.87.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + +"request@>=2.9.0 <2.82.0": + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + +resolve-id-refs@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/resolve-id-refs/-/resolve-id-refs-0.1.0.tgz#3126624b887489da8fc0ae889632f8413ac6c3ec" + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.3, resolve@^1.1.4, resolve@^1.1.5, resolve@^1.4.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + +rimraf@2, rimraf@^2.5.2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" + dependencies: + glob "^7.0.5" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + dependencies: + aproba "^1.1.1" + +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + +safer-eval@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/safer-eval/-/safer-eval-1.2.3.tgz#73ba74a34bc8a07d6a44135c815fd18a8eebe7a0" + dependencies: + clones "^1.1.0" + +sass-graph@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" + dependencies: + glob "^7.0.0" + lodash "^4.0.0" + scss-tokenizer "^0.2.3" + yargs "^7.0.0" + +sax@^1.2.4, sax@~1.2.1, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + +scss-tokenizer@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" + dependencies: + js-base64 "^2.1.8" + source-map "^0.4.2" + +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + dependencies: + semver "^5.0.3" + +"semver@2 >=2.2.1 || 3.x || 4 || 5", "semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", "semver@^2.3.0 || 3.x || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +send@0.16.2: + version "0.16.2" + resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.6.2" + mime "1.4.1" + ms "2.0.0" + on-finished "~2.3.0" + range-parser "~1.2.0" + statuses "~1.4.0" + +serialize-to-js@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/serialize-to-js/-/serialize-to-js-1.2.1.tgz#2e87f61f938826d24c463a7cbd0dd2929ec38008" + dependencies: + js-beautify "^1.7.5" + safer-eval "^1.2.3" + +serve-static@^1.12.4: + version "1.13.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.2" + send "0.16.2" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + +set-value@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.1" + to-object-path "^0.3.0" + +set-value@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + +sha.js@^2.4.0, sha.js@^2.4.8, sha.js@~2.4.4: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +sha@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" + dependencies: + graceful-fs "^4.1.2" + readable-stream "^2.0.2" + +shallow-copy@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" + +shasum@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" + dependencies: + json-stable-stringify "~0.0.0" + sha.js "~2.4.4" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +shell-quote@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.6.1.tgz#f4781949cce402697127430ea3b3c5476f481767" + dependencies: + array-filter "~0.0.0" + array-map "~0.0.0" + array-reduce "~0.0.0" + jsonify "~0.0.0" + +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + dependencies: + is-arrayish "^0.3.1" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slide@^1.1.3, slide@^1.1.6, slide@~1.1.3, slide@~1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +smart-buffer@^1.0.13: + version "1.1.15" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-1.1.15.tgz#7f114b5b65fab3e2a35aa775bb12f0d1c649bf16" + +smart-buffer@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.0.1.tgz#07ea1ca8d4db24eb4cac86537d7d18995221ace3" + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +socks-proxy-agent@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-3.0.1.tgz#2eae7cf8e2a82d34565761539a7f9718c5617659" + dependencies: + agent-base "^4.1.0" + socks "^1.1.10" + +socks-proxy-agent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.1.tgz#5936bf8b707a993079c6f37db2091821bffa6473" + dependencies: + agent-base "~4.2.0" + socks "~2.2.0" + +socks@^1.1.10: + version "1.1.10" + resolved "https://registry.yarnpkg.com/socks/-/socks-1.1.10.tgz#5b8b7fc7c8f341c53ed056e929b7bf4de8ba7b5a" + dependencies: + ip "^1.1.4" + smart-buffer "^1.0.13" + +socks@~2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.2.1.tgz#68ad678b3642fbc5d99c64c165bc561eab0215f9" + dependencies: + ip "^1.1.5" + smart-buffer "^4.0.1" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + dependencies: + is-plain-obj "^1.0.0" + +sorted-object@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" + +sorted-union-stream@~2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/sorted-union-stream/-/sorted-union-stream-2.1.3.tgz#c7794c7e077880052ff71a8d4a2dbb4a9a638ac7" + dependencies: + from2 "^1.3.0" + stream-iterate "^1.1.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@^0.4.15: + version "0.4.18" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" + dependencies: + source-map "^0.5.6" + +source-map-support@~0.5.6: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13" + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + +source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + +source-map@^0.4.2: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + +spdx-correct@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz#7a7cd28470cc6d3a1cfe6d66886f6bc430d3ac87" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +sshpk@^1.7.0: + version "1.14.2" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + safer-buffer "^2.0.2" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +ssri@^5.2.4: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-5.3.0.tgz#ba3872c9c6d33a0704a7d71ff045e5ec48999d06" + dependencies: + safe-buffer "^5.1.1" + +ssri@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.0.tgz#fc21bfc90e03275ac3e23d5a42e38b8a1cbc130d" + +stable@~0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + +static-eval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.0.0.tgz#0e821f8926847def7b4b50cda5d55c04a9b13864" + dependencies: + escodegen "^1.8.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +static-module@^2.2.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/static-module/-/static-module-2.2.5.tgz#bd40abceae33da6b7afb84a0e4329ff8852bfbbf" + dependencies: + concat-stream "~1.6.0" + convert-source-map "^1.5.1" + duplexer2 "~0.1.4" + escodegen "~1.9.0" + falafel "^2.1.0" + has "^1.0.1" + magic-string "^0.22.4" + merge-source-map "1.0.4" + object-inspect "~1.4.0" + quote-stream "~1.0.2" + readable-stream "~2.3.3" + shallow-copy "~0.0.1" + static-eval "^2.0.0" + through2 "~2.0.3" + +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + +statuses@~1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" + +stdout-stream@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/stdout-stream/-/stdout-stream-1.4.0.tgz#a2c7c8587e54d9427ea9edb3ac3f2cd522df378b" + dependencies: + readable-stream "^2.0.1" + +stream-browserify@^2.0.0, stream-browserify@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-combiner2@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stream-combiner2/-/stream-combiner2-1.1.1.tgz#fb4d8a1420ea362764e21ad4780397bebcb41cbe" + dependencies: + duplexer2 "~0.1.0" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.0.0, stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-iterate@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/stream-iterate/-/stream-iterate-1.2.0.tgz#2bd7c77296c1702a46488b8ad41f79865eecd4e1" + dependencies: + readable-stream "^2.1.5" + stream-shift "^1.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + +stream-splicer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/stream-splicer/-/stream-splicer-2.0.0.tgz#1b63be438a133e4b671cc1935197600175910d83" + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.2" + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + +string-width@^1.0.1, string-width@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@^1.0.0, string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +string_decoder@~0.10.0, string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +stringify-package@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.0.tgz#e02828089333d7d45cd8c287c30aa9a13375081b" + +stringstream@~0.0.4: + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +stylehacks@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.0.tgz#64b323951c4a24e5fc7b2ec06c137bf32d155e8a" + dependencies: + browserslist "^4.0.0" + postcss "^6.0.0" + postcss-selector-parser "^3.0.0" + +subarg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" + dependencies: + minimist "^1.1.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +supports-color@^5.3.0, supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + +svgo@^0.7.0: + version "0.7.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" + dependencies: + coa "~1.0.1" + colors "~1.1.2" + csso "~2.3.1" + js-yaml "~3.7.0" + mkdirp "~0.5.1" + sax "~1.2.1" + whet.extend "~0.9.9" + +svgo@^1.0.0, svgo@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.0.5.tgz#7040364c062a0538abacff4401cea6a26a7a389a" + dependencies: + coa "~2.0.1" + colors "~1.1.2" + css-select "~1.3.0-rc0" + css-select-base-adapter "~0.1.0" + css-tree "1.0.0-alpha25" + css-url-regex "^1.1.0" + csso "^3.5.0" + js-yaml "~3.10.0" + mkdirp "~0.5.1" + object.values "^1.0.4" + sax "~1.2.4" + stable "~0.1.6" + unquote "~1.1.1" + util.promisify "~1.0.0" + +syntax-error@^1.1.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/syntax-error/-/syntax-error-1.4.0.tgz#2d9d4ff5c064acb711594a3e3b95054ad51d907c" + dependencies: + acorn-node "^1.2.0" + +tar@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +tar@^4, tar@^4.4.3, tar@^4.4.4: + version "4.4.6" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" + dependencies: + chownr "^1.0.1" + fs-minipass "^1.2.5" + minipass "^2.3.3" + minizlib "^1.1.0" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.2" + +term-size@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + dependencies: + execa "^0.7.0" + +terser@^3.7.3: + version "3.8.1" + resolved "https://registry.yarnpkg.com/terser/-/terser-3.8.1.tgz#cb70070ac9e0a71add169dfb63c0a64fca2738ac" + dependencies: + commander "~2.16.0" + source-map "~0.6.1" + source-map-support "~0.5.6" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through2@^2.0.0, through2@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +"through@>=2.2.7 <3": + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + +timers-browserify@^1.0.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-1.4.2.tgz#c9c58b575be8407375cb5e2462dacee74359f41d" + dependencies: + process "~0.11.0" + +timers-browserify@^2.0.4: + version "2.0.10" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.10.tgz#1d28e3d2aadf1d5a5996c4e9f95601cd053480ae" + dependencies: + setimmediate "^1.0.4" + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + +tiny-inflate@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.2.tgz#93d9decffc8805bd57eae4310f0b745e9b6fb3a7" + +tiny-relative-date@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/tiny-relative-date/-/tiny-relative-date-1.3.0.tgz#fa08aad501ed730f31cc043181d995c39a935e07" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toml@^2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/toml/-/toml-2.3.3.tgz#8d683d729577cb286231dfc7a8affe58d31728fb" + +tomlify-j0.4@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tomlify-j0.4/-/tomlify-j0.4-3.0.0.tgz#99414d45268c3a3b8bf38be82145b7bba34b7473" + +tough-cookie@~2.3.0, tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +"true-case-path@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/true-case-path/-/true-case-path-1.0.2.tgz#7ec91130924766c7f573be3020c34f8fdfd00d62" + dependencies: + glob "^6.0.4" + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + +tty-browserify@~0.0.0: + version "0.0.1" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6, typedarray@~0.0.5: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +typescript@^2.4.1: + version "2.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.2.tgz#1cbf61d05d6b96269244eb6a3bce4bd914e0f00c" + +uglify-es@^3.3.9: + version "3.3.10" + resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.3.10.tgz#8b0b7992cebe20edc26de1bf325cef797b8f3fa5" + dependencies: + commander "~2.14.1" + source-map "~0.6.1" + +uid-number@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +umask@^1.1.0, umask@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" + +umd@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" + +undeclared-identifiers@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/undeclared-identifiers/-/undeclared-identifiers-1.1.2.tgz#7d850a98887cff4bd0bf64999c014d08ed6d1acc" + dependencies: + acorn-node "^1.3.0" + get-assigned-identifiers "^1.2.0" + simple-concat "^1.0.0" + xtend "^4.0.1" + +unicode-trie@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/unicode-trie/-/unicode-trie-0.3.1.tgz#d671dddd89101a08bac37b6a5161010602052085" + dependencies: + pako "^0.2.5" + tiny-inflate "^1.0.0" + +union-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^0.4.3" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + +unique-filename@^1.1.0, unique-filename@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.0.tgz#d05f2fe4032560871f30e93cbe735eea201514f3" + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.0.tgz#db6676e7c7cc0629878ff196097c78855ae9f4ab" + dependencies: + imurmurhash "^0.1.4" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + +unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +upath@^1.0.5: + version "1.1.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + +update-notifier@^2.3.0, update-notifier@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" + dependencies: + boxen "^1.2.1" + chalk "^2.0.1" + configstore "^3.0.0" + import-lazy "^2.1.0" + is-ci "^1.0.10" + is-installed-globally "^0.1.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + +url@^0.11.0, url@~0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + +uswds@^1.6.3: + version "1.6.7" + resolved "https://registry.yarnpkg.com/uswds/-/uswds-1.6.7.tgz#85ffa94a26da333e7e709b9fbc7292edab04ac82" + dependencies: + "@types/node" "^8.5.5" + array-filter "^1.0.0" + array-foreach "^1.0.2" + browserify "^13.0.0" + classlist-polyfill "^1.0.3" + domready "^1.0.8" + elem-dataset "^1.1.1" + lodash.debounce "^4.0.7" + object-assign "^4.1.1" + receptor "^1.0.0" + resolve-id-refs "^0.1.0" + typescript "^2.4.1" + yargs "^8.0.2" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +util-extend@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" + +util.promisify@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +util@^0.10.3, util@~0.10.1: + version "0.10.4" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.4.tgz#3aa0125bfe668a4672de58857d3ace27ecb76901" + dependencies: + inherits "2.0.3" + +uuid@^3.0.0, uuid@^3.1.0, uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + +v8-compile-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.0.tgz#526492e35fc616864284700b7043e01baee09f0a" + +validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz#81643bcbef1bdfecd4623793dc4648948ba98338" + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + dependencies: + builtins "^1.0.3" + +vendors@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.2.tgz#7fcb5eef9f5623b156bcea89ec37d63676f21801" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vlq@^0.2.2: + version "0.2.3" + resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" + +vm-browserify@0.0.4, vm-browserify@~0.0.1: + version "0.0.4" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" + dependencies: + indexof "0.0.1" + +vue@^2.5.17: + version "2.5.17" + resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.17.tgz#0f8789ad718be68ca1872629832ed533589c6ada" + +wcwidth@^1.0.0, wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + dependencies: + defaults "^1.0.3" + +whet.extend@~0.9.9: + version "0.9.9" + resolved "https://registry.yarnpkg.com/whet.extend/-/whet.extend-0.9.9.tgz#f877d5bf648c97e5aa542fadc16d6a259b9c11a1" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + +which@1, which@^1.2.9, which@^1.3.0, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + dependencies: + string-width "^1.0.2 || 2" + +widest-line@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" + dependencies: + string-width "^2.1.1" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +worker-farm@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.6.0.tgz#aecc405976fab5a95526180846f0dba288f3a4a0" + dependencies: + errno "~0.1.7" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +ws@^5.1.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" + dependencies: + async-limiter "~1.0.0" + +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yallist@^3.0.0, yallist@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.2.tgz#8452b4bb7e83c7c188d8041c1a837c773d6d8bb9" + +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" + dependencies: + camelcase "^4.1.0" + +yargs-parser@^9.0.2: + version "9.0.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" + dependencies: + camelcase "^4.1.0" + +yargs@^11.0.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" + dependencies: + cliui "^4.0.0" + decamelize "^1.1.1" + find-up "^2.1.0" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^9.0.2" + +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + +yargs@^8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1" + yargs-parser "^7.0.0"