From c3081911960ca153ed145c418e2065817cf9ddd4 Mon Sep 17 00:00:00 2001 From: Diego Lendoiro Date: Thu, 5 Dec 2019 16:20:05 +0100 Subject: [PATCH 001/287] Changed: typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49a0ff7217..4f7985cf5f 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ GNU Affero General Public License for more details. Passbolt is an open source password manager for teams. It allows you to securely share and store credentials. For instance, the wifi password of your -office, the administrator password of a router or your organisation's social +office, the administrator password of a router or your organization's social media account passwords, all of them can be secured using passbolt. Passbolt is different from the other password managers because: From 9688aada3c06238d24db11a06043c3a3a71881c7 Mon Sep 17 00:00:00 2001 From: Remy Bertot Date: Wed, 3 Jun 2020 18:17:36 +0200 Subject: [PATCH 002/287] Update test fixture expired key (ruth) --- tests/Fixture/Gpgkeys/ruth_public.key | 97 +++++++++++++-------------- 1 file changed, 48 insertions(+), 49 deletions(-) diff --git a/tests/Fixture/Gpgkeys/ruth_public.key b/tests/Fixture/Gpgkeys/ruth_public.key index 3c1ee8ab3a..138c96ad92 100644 --- a/tests/Fixture/Gpgkeys/ruth_public.key +++ b/tests/Fixture/Gpgkeys/ruth_public.key @@ -1,52 +1,51 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -Comment: GPGTools - https://gpgtools.org -mQINBFdIFUwBEACwWLN9l8cObl/dJVsXpGsGdmtoSr8mg2ATA/i/Jc1m7n9Pn2PB -usXohI2WWGVU92k5MntugYuZTeo6m5gMkqiUGfpnyxbojqziJSviTpwCMtl0Ja8v -FZpUwtkrSYTfkz+LaIszBM26ZrYB2kAmoTBzIdMGruQW/47DSLLDqN2/tSW9275/ -OjrBiD1p0dfUR/CLbt16CHuKCgc8EjgIZfO+qJDpUJ8KKi/c1d7CoeYsWfsuNZKn -RnKWEe7oLX6tFpqrvkoiXXfWvOQJ2bZoNSFE1/jkGK0vn74Pdozs5ijWg0Npg2o8 -CB2YoXH630fL/aiky5Yu6NoFJI8U8bHW/v5SOF/LlLy05M78hEqiL/p3JVv0Dz5f -mZl/ajbi4iuLpAU9vKb7I2LhUaj3jKTaAYQj1b1NOm+9c92wVm4LCuJfwAZyFSxm -FGJF3RZaKPnWBXQov0MmNFtJFeGhxv0ZrivD5a2PFdsPDeJ49rXdwRt4VHa1dcA3 -rwQMboDMYgsalDbEeI5yQkB1SrjkZ2cExq2kJEIKRRlUzUBxBHGKpaMeom0au1J4 -AdR0lFRFoNojHB0TfVxSZ1FrQubUf1UoOzaX+JniwLlSFcUNLs4HJJ0XQnmBgCvT -b0+jKLjiXf/wUYPTuUP2xW8MgWt/W/Mp5WmPHAik2MfT2wyvGvCmoX6TxQARAQAB -tCNSdXRoIFRlaXRlbGJhdW0gPHJ1dGhAcGFzc2JvbHQuY29tPokCPQQTAQoAJwUC -V0gVTAIbAwUJB4YfgAULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRBUa0eHo6Ku -lzzZD/0f/jjXR96+ipUUQNkcY8P1CbkzQOgG8o69fwyhArSBLRyCKZC9X1c6JKPc -40HCtEnNc6kvZv63eC/AMBm2wmX8QBcqzy4lr5pSRXnMHZ68IyajKyllg54CbdMP -/vEhT0LU3BI49FVknzKuk9/v974SLXrzioUpzMMJdjblTqHeEUJkxQZVYIjO4vWL -7F7dm/nYBEi5iFlG7QBJOwjLj1RwWbKZRWVft7Ybgk1jb+AZBBHTKZWTrvkfV9Bs -kxhmZl/+tSXtkpEUFyFgdFcl3c1jbd2iXq2mTEi4/widYM1ty+kcqQ29bjYat/ix -h3bEnoyicSvbUpl/6tLmZ495J8isiD46kHKjXVaBXAL9n1of3pf4HVogDZLhhZdB -eOWBoEenAooie8b90BJ8l+sCenJMCuR8dGO3Rd/bmMmLE2beu1SLO9c2F7O7//Kb -Wg2sP8aFeIwChpQ2CkGVSJrs82gjj0wcwVtys1eFSz9cq8QTGZrIluO5NmgbqI7x -z88p0mQ/ud/wljYb5rk92zPvGB0hiHaH+fO543zwerEyHew115dnrX5XoELtwem7 -DHHCY/Q3yiQ+LiYHDQN5IXg77vPiHnn8JS49HAOvw32mMlrRIQwLLEAlw+OB4k5V -AInZrZIi46ZHDMogN/Kgd8b/P0ot+Nm1dflAuAHAUZhSYF4XELkCDQRXSBVMARAA -zRrvVmDmSqRZPIZzE/dHGI+tPYoJIcuXagNCzXld2LEgzU9I6iKsxEIQeKGj/g5r -kHzDMCMEfi1K0g50AuD4f9Sa6SBM+zLUZcimZQjAWVIa8rqYnpMi/SQjsGrUjf79 -TMGRspr5pKXZNARCVyFijf5KqKHggdcpDeUUkr+l2SpZ+w6alJ6T9vlzqPSM34RN -Odeef//Ye+q7ncxB4elmPYzw9zLOZd90SbVjX1k/L6E0z4VVYQk2Qvo3jwzj+b2s -fd1j1ygCplm1poHrDh2mMVdl+DVCdM3Xq6PEwmVAvCdqOMrOBfrvZ2GC+wPgBvFl -PZ3Ve9LWCqSklpAh1JdRsVOvESvJ76YR3zSi0ta4gfqJFUTj6AnO4U5IF0H8eYHT -rnsXRW16ab0GX0ozPI3L9GrfSkPaZa+QOKsqvNc/m18mYIeYqtdtrA2IUvYR8MFm -EIVu4aojRKqmlrgqKi4oplevtMURZ0j/D81qun32yF2lRO+wdP/JW5hNmS0roCYf -p/uVBteREQzz+s3zqZGJ22u7EfdaPFOUAxJiBqA1OKKeIV+V5O3k164oSGmhnvkf -T79HpbkY67FnXAOf/MVowhQgBZxy+ZNd9QjVqBVF6Owjr/hk5dV+LBPLn1MVxh3P -cnezoPB5pXjvhZkG/kC6AUIF6aHdCYMJomKZmA/RdY0AEQEAAYkCJQQYAQoADwUC -V0gVTAIbDAUJB4YfgAAKCRBUa0eHo6Kul2eUD/9IvZ3MsJpVmSy8xMphFrl/5eVY -Fih/FN9FQ9Gm18NR4XcubHU2IEJ7cnk/Y4LSKnhSa8Ec/IDnxaDjKgIo/aZz5UPc -3y1XbX3T1XeztVixWzVdwr5wON4Ad2cFQKvLeDrP1ZlTM84sT113MoifscpiFu8/ -2DxNWQ2wtlwg30e6g16xd6eKDMRUP6mUo+EElRbuV9uu3zlHFnLXKbKLxeC/12DA -uRcCTQ2wZbQgGr4mDp5BJ9E28t2e7nzgUTB/opCEFLbK7udtVK3BhymPngJz3quy -Vd3tNnrHIM5d5xPsQkJN0O/XpPE3FDRGKAcPpoAFEU86DogkNFkp7aezVzc+pwzB -Ek+Tj1XnspDJRxfjCSkxgFgJA5rUuf/9W9x87sCW5baLX3s3fbDeOJN2kaGHWsGj -NqM6+nxFv5ZfTUgOKdTTlfwuYGdrPfcms3zgJPOVlnw1lKjZCGZHMcwjFeyEWzBd -QJsO/B6pjGJnW2Ap3ixljClk1h8d2uB+tSbjUBjY9rNapPotKqoM17uagEPtiWJT -+uagais8L/KE+0mEmlkfQFFvWUivqzriE949LePBqbMa7tuUP96+z1MIptg1YRnA -lL0W0GCoHYfLyD2UgF1gNuoFH5vg3HFvHHN+hDQvWd4LvEf/zW0GFZdscL7FGqup -xmbuDQiLNivOI9WNWQ== -=nSho +mQINBF7OcSMBEADJVDPnmOVmCour/wqpTTOicP7+buLpUxQsn8m4t6K/J+ratg8A +9+0kp6zK+jSHRT92mTVrY6RP7pRoZUBVe+7t92POf7+SJK8LumD7M9te+rAmrc8Z +721IopSZb3aHhFDmVDYHWaW+KzKWVRdP3O7ECy94s8vMqEOB3A0anAEFWx4VIZGK +xBJ+qtfMSiyVU+BB/585mkPaHPvqN7FZ1pA7LtwPCXZ5m000UiFukkNHVs4aLIbc +113NM9sOAumsurpg0jDB3Uh5rlpWKICZmhD1JNr9E41BcxrK53tnZ5KRc+z9k0pP +cfoYCoebIG1OuLJ9owM0NAcNk8EYbRUyT4IBrZkKWV1CH0QQorNPXuharrQHYt02 +Bvn81L7jdSg3fzGnv47SRWWkzG8JY65UZbVKepgZdJHzmx9wCnFn0lVfjhN86kV+ +EZkTklBhMirmM82BfFFn7/fcsVIIlPYEiiP173zCWS3rFTTkM+BJB5XZ8YJHRleP +lssPs79euWgdSomCXQOmoy6D6ZJIES9gyShIOfBtAICNQG9KRNJBzk2TZDgYSCNT +ohC4C7ZC31Ol1xML/buihW+3eaqMzscwq5KAKbQ9B06rkTd16LxUe6nS25Dt2Ngy +ks7CyB1QUT+sZNLbm6cljfveqnw+zV1Zg61PNtUYf85RCtOpSbWsBG1fXQARAQAB +tCNSdXRoIFRlaXRlbGJhdW0gPHJ1dGhAcGFzc2JvbHQuY29tPokCTgQTAQgAOBYh +BHp5WlGkq+xKeapku9Wjym76hY3uBQJeznEjAhsDBQsJCAcCBhUKCQgLAgQWAgMB +Ah4BAheAAAoJENWjym76hY3uCwwQAK66JganlMibCH8UKHuke2kBboVJIJT8TAI7 +beOC70SNwd6C5jLYFLiath8M5xkdkivMZ6REr9FkIzxMWa4/6ICQ4Ve7pHpm/oz2 +9keFVjAQyeh4kc/fHNlYTWnTxhMMUziNdetL30yGdt64Y7vjeqQz6YgOD7s4gSQD +zoI9j0S+fshuBeYtIuVn7DOT+ycqTdZzEGEp7OnOyHme4i4OE1fFvWSOKVxP6PLd +HrEJcF/EXvN632KO6aC8sPrMxgpST6H2EpCXKDXhpZgvLXPVvlbsJsrqkaqzXa61 +pGbfZegBfjSZfoRl2Q9L6g4KvaqcU49btD1EB0uq/22jz9sPjCGMdmv+8iSdd1lv +M70l5RhvDq4AVOKkG6pxGLB3njma2d5QkxygKRtg+/4B9K8Ml34QWZvSdIpxjSum +MWusXW+xa1C5uiGo3sTUFZJgvIkxRmiNsFTEmYXqgUQYaThGJZ9qY28mZEVnv1cR +NW/9EIdjfL6c1pN54Vb8hnZVyBE5xRyRZEyUZIPrTPoGKUOSK7qqGmrKduXTsq5R +trym/BI1/jq306ZfHDXewZ1F53hQkKoVSjoM/T59IO7Ia1mzlV7zUmwVsvX7JveD +nZIWeP92SRwdJllbtEjZ/aKUwN9+NuA5Q9ZxYKYKCGsVCA871xxY5SXeW/wqgMwx +ElKqBpYSuQINBF7OcSMBEADp4/7Q3Et5BXezjcjKs10/gR81HCCslU51rQ3XxOYI +dENacf/8e55DPXw9AXhCEgdUXXp+HzapeUDM8B4WxJq0TUGBOJbKj7LDs/f3hzLR +XqncYwaARDDeO/3B0YubHYgqaJG9M6pB2EmkWuM/FJsTZzqdDqFygNm7QAlJu/7z +AupvhcAiv9dvpwefHUVvByddDF81nG436P9GlFW6/0HmyOSrZCtITqQ5MiP0wAVl +gSqktSkQwMNLE9nlRJxPb3pTWdWK6SaLN9C+BFRU9frciYpPTfCq+IfQr9dHwwAY +KdMlNjCCMWTzYVO85ExGhVjMP6GzVoEzl8xMl4LtPvckf4j/YQ9eSMRPMjH5cgeF +vPpetbu1LsJHGzEozSBm3qL7pOFExUpnR5yLvmVbavPmEqL91uUR7ECl2pXKq0ny +GYShEEVCD80DG7KGoOTQJwBsAcPu0PxzTmEzyfpCcplmAJm0AP7IHxk6r8o3rXCU +WiQWHdV5kzS7ARdJOlLXwiGFq9OhnqlBaoweoLRwctPYCErC5iUEw9LuWCcr035P +SGvOupyeaEZBrvbDx1rv88UDCWbeNARB32A14Y7JeW+571BWKpt/wQ66LG1k5b2D +pOMzLNir1dgUkPz9WZPiCEtDQzoTxkqf9MGGmawGRWOA3ILkG/ye8UNDsCOmU4tD +EQARAQABiQI2BBgBCAAgFiEEenlaUaSr7Ep5qmS71aPKbvqFje4FAl7OcSMCGwwA +CgkQ1aPKbvqFje6+uxAAwASA8FYA9lZxDFhQC+fYUXTH6MfyCs+pOfRboGI9y8ai +dMrwTaWqKoTX+t5eaKDARFDGoJdKzHyuesoHJJ27vqJYJ3aBAxwZHb9ZZR73tMWX +oqsYir+x/x+CJ1G1bjJDgf3PFtZdc6R3WC8BpMKAaVlDVqGzAR8PaJms7DDeAjES +hWkDmoSpU7P0FFzCH1xm73fxqWHHf9yfZXRCfL0G4R58psQT9VKaL8/6eI5bKOxS +LJzgLk2BW802dYJXSwTzFVQQL9kZUNrFtjNQzcPwhGFmQ4l/IH0vArBEDmtFeRba +QsCKJkwn0AoyvCygr+5bnUPR8xI4mCnBl9fRan4Rg6i7iZpX6h23eRaj4wXvmxtr +QNyzaHeBSI3GkUKdkY+L00H6/5F+dEYjCYHw8dO1UEAUnulTneG+viqXPR+v/Mt3 +QjNc31ZOJn29P2IgzElh0LQZUsGTYmkmwCr/0+CW7lSdZYXOffIkmUvSVfJjPonA +c7IXs32tLybfB6NVSqRfJNLJ+jCJUDRjou36xvetnGTYUXtWCMllrRi0bVqHGdTs +cL9F6SQqgkTXWYg7PCNX/ZchzrhS6eamJL7dsN7sQ6gJXNiTsezNNJl2qfvZGTCr +gv4VvNhm6h0zKx86FSS/Hlgm/ge2e3w1eaGW25a17tmGOh6f/euxLnHVnaNiNW4= +=y2sM -----END PGP PUBLIC KEY BLOCK----- From dc37449a1307eff6668163d8872daf0afc0e7a58 Mon Sep 17 00:00:00 2001 From: Diego Lendoiro Date: Mon, 25 May 2020 11:25:59 +0000 Subject: [PATCH 003/287] Merge branch 'feature/debian-package' into 'common' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 📦 Debian package See merge request passbolt/passbolt-pro-api!116 --- .gitignore | 10 + .gitlab-ci.yml | 5 + .gitlab-ci/Jobs/debian_package_build.yml | 139 ++++ .gitlab-ci/Jobs/php_unit_tests.yml | 4 + Berksfile | 5 + Berksfile.lock | 6 + Gemfile | 11 + Gemfile.lock | 655 ++++++++++++++++++ chefignore | 1 + debian/README.debian.md | 130 ++++ debian/changelog | 24 + debian/compat | 1 + debian/conf/nginx-passbolt-ssl.conf | 20 + debian/conf/nginx-passbolt.conf | 45 ++ debian/config | 310 +++++++++ debian/control | 29 + debian/control.in | 30 + debian/copyright | 133 ++++ debian/cron.d.in | 12 + debian/dirs | 4 + debian/docs.in | 2 + debian/install | 19 + debian/lintian-overrides.in | 4 + debian/logrotate.in | 9 + debian/patches/01_paths_setup.patch | 80 +++ debian/patches/02_webpaths_setup.patch | 13 + debian/patches/03_cake_import_paths.patch | 19 + debian/patches/series | 3 + debian/postinst | 275 ++++++++ debian/postrm | 96 +++ debian/preinst | 29 + debian/prepare-files | 5 + debian/rules | 68 ++ debian/source/format | 1 + debian/templates | 138 ++++ debian/triggers.in | 5 + kitchen.yml | 53 ++ .../passbolt_package/.delivery/project.toml | 32 + tests/cookbooks/passbolt_package/.gitignore | 22 + tests/cookbooks/passbolt_package/metadata.rb | 7 + .../recipes/passbolt_install.rb | 16 + .../recipes/passbolt_install_and_purge.rb | 14 + .../passbolt_install_break_and_recover.rb | 28 + .../recipes/passbolt_install_breaks.rb | 15 + .../recipes/passbolt_install_mariadb_nginx.rb | 20 + .../recipes/passbolt_package_build.rb | 46 ++ .../recipes/passbolt_responses_nginx_mysql.rb | 26 + .../break-benchmarks/controls/break.rb | 11 + tests/integration/break-benchmarks/inspec.yml | 8 + .../filesystem-benchmarks/README.md | 3 + .../controls/configuration.rb | 143 ++++ .../filesystem-benchmarks/controls/source.rb | 68 ++ .../controls/systemfiles.rb | 93 +++ .../filesystem-benchmarks/controls/webroot.rb | 53 ++ .../filesystem-benchmarks/inspec.yml | 8 + .../filesystem-benchmarks/libraries/.gitkeep | 0 .../purge-benchmarks/controls/cache.rb | 10 + .../purge-benchmarks/controls/purge.rb | 29 + tests/integration/purge-benchmarks/inspec.yml | 8 + .../runtime-benchmarks/controls/cache.rb | 10 + .../controls/healthcheck.rb | 21 + .../runtime-benchmarks/controls/mysql.rb | 13 + .../integration/runtime-benchmarks/inspec.yml | 8 + 63 files changed, 3105 insertions(+) create mode 100644 .gitlab-ci/Jobs/debian_package_build.yml create mode 100644 Berksfile create mode 100644 Berksfile.lock create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 chefignore create mode 100644 debian/README.debian.md create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/conf/nginx-passbolt-ssl.conf create mode 100644 debian/conf/nginx-passbolt.conf create mode 100755 debian/config create mode 100644 debian/control create mode 100644 debian/control.in create mode 100644 debian/copyright create mode 100644 debian/cron.d.in create mode 100644 debian/dirs create mode 100644 debian/docs.in create mode 100755 debian/install create mode 100644 debian/lintian-overrides.in create mode 100644 debian/logrotate.in create mode 100644 debian/patches/01_paths_setup.patch create mode 100644 debian/patches/02_webpaths_setup.patch create mode 100644 debian/patches/03_cake_import_paths.patch create mode 100644 debian/patches/series create mode 100755 debian/postinst create mode 100755 debian/postrm create mode 100755 debian/preinst create mode 100644 debian/prepare-files create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 debian/templates create mode 100644 debian/triggers.in create mode 100644 kitchen.yml create mode 100644 tests/cookbooks/passbolt_package/.delivery/project.toml create mode 100644 tests/cookbooks/passbolt_package/.gitignore create mode 100644 tests/cookbooks/passbolt_package/metadata.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_install.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_install_and_purge.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_install_break_and_recover.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_install_breaks.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_install_mariadb_nginx.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_package_build.rb create mode 100644 tests/cookbooks/passbolt_package/recipes/passbolt_responses_nginx_mysql.rb create mode 100644 tests/integration/break-benchmarks/controls/break.rb create mode 100644 tests/integration/break-benchmarks/inspec.yml create mode 100644 tests/integration/filesystem-benchmarks/README.md create mode 100644 tests/integration/filesystem-benchmarks/controls/configuration.rb create mode 100644 tests/integration/filesystem-benchmarks/controls/source.rb create mode 100644 tests/integration/filesystem-benchmarks/controls/systemfiles.rb create mode 100644 tests/integration/filesystem-benchmarks/controls/webroot.rb create mode 100644 tests/integration/filesystem-benchmarks/inspec.yml create mode 100644 tests/integration/filesystem-benchmarks/libraries/.gitkeep create mode 100644 tests/integration/purge-benchmarks/controls/cache.rb create mode 100644 tests/integration/purge-benchmarks/controls/purge.rb create mode 100644 tests/integration/purge-benchmarks/inspec.yml create mode 100644 tests/integration/runtime-benchmarks/controls/cache.rb create mode 100644 tests/integration/runtime-benchmarks/controls/healthcheck.rb create mode 100644 tests/integration/runtime-benchmarks/controls/mysql.rb create mode 100644 tests/integration/runtime-benchmarks/inspec.yml diff --git a/.gitignore b/.gitignore index d30b17539e..67cf5044d0 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,13 @@ atlassian-ide-plugin.xml com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties +.kitchen/ +.kitchen.local.yml +debian/tmp/ +debian/passbolt-ce/ +debian/.debhelper/ +debian/files +debian/passbolt-api-ce/ +debian/passbolt-api-pro/ +debian/*debhelper* +debian/*substvars* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 001ef87e1a..edbf3f51f9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,15 +3,20 @@ image: alpine:latest variables: DOCKER_HOST: tcp://localhost:2375 DOCKER_DRIVER: overlay2 + DOCKER_TLS_CERTDIR: "" stages: + - deps + - build - test - release + - publish include: - template: Code-Quality.gitlab-ci.yml - local: '/.gitlab-ci/Jobs/php_unit_tests.yml' - local: '/.gitlab-ci/Jobs/artifact_build.yml' + - local: '/.gitlab-ci/Jobs/debian_package_build.yml' - local: '/.gitlab-ci/Jobs/style_check.yml' ############################################################ diff --git a/.gitlab-ci/Jobs/debian_package_build.yml b/.gitlab-ci/Jobs/debian_package_build.yml new file mode 100644 index 0000000000..1282c9c664 --- /dev/null +++ b/.gitlab-ci/Jobs/debian_package_build.yml @@ -0,0 +1,139 @@ +services: + - docker:19.03.0-dind + +.dependencies: + image: $PACKAGE_MANAGER_IMAGE + stage: deps + artifacts: + paths: + - $PACKAGE_MANAGER_PATH + expire_in: 1 days + when: always + cache: + paths: + - $PACKAGE_MANAGER_PATH + +composer: + extends: .dependencies + variables: + PACKAGE_MANAGER_IMAGE: "composer:latest" + PACKAGE_MANAGER_PATH: vendor/ + script: + - | + composer global require hirak/prestissimo + composer install --prefer-dist -o --no-dev --ignore-platform-reqs --no-interaction + +build-debian: + image: debian:stable-slim + stage: build + dependencies: + - composer + artifacts: + paths: + - '*.deb' + - '*.build' + - '*.buildinfo' + - '*.changes' + expire_in: 1 week + when: always + script: + - | + apt-get update + apt-get install -y devscripts apt-utils debconf-utils fakeroot equivs cdbs + make -f debian/rules debian/control + mk-build-deps -irt'apt-get --no-install-recommends -yV' debian/control + dpkg-checkbuilddeps + debuild --preserve-envvar PASSBOLT_FLAVOUR -us -uc -b -i -I + cp ../*.deb . + cp ../*.build . + cp ../*.buildinfo . + cp ../*.changes . + +.kitchen-test: + image: chef/chefdk:latest + stage: test + dependencies: + - composer + - build-debian + script: + - gem install bundler:2.1.2 + - kitchen verify $KITCHEN_JOB -t tests/integration + except: + variables: + - $CI_COMMIT_MESSAGE =~ /skip-integration/ + +.publish: + image: registry.gitlab.com/passbolt/passbolt-ops/passbolt-aptly + stage: publish + dependencies: + - build-debian + script: + - /publisher.sh + only: + variables: + - $CI_COMMIT_MESSAGE =~ /publish-package/ + +dist-debian: + extends: .publish + variables: + DISTRIBUTION: buster + COMPONENT: stable + PREFIX: $PASSBOLT_FLAVOUR/debian + +debian-fs: + extends: .kitchen-test + dependencies: + - composer + variables: + KITCHEN_JOB: filesystem-benchmarks-debian-buster + +debian-purge: + extends: .kitchen-test + variables: + KITCHEN_JOB: purge-benchmarks-debian-buster + +debian-runtime: + extends: .kitchen-test + variables: + KITCHEN_JOB: runtime-benchmarks-debian-buster + +debian-break: + extends: .kitchen-test + variables: + KITCHEN_JOB: break-benchmarks-debian-buster + +ubuntu-1804-fs: + extends: .kitchen-test + allow_failure: true + variables: + KITCHEN_JOB: filesystem-benchmarks-ubuntu-1804 + +ubuntu-1804-purge: + extends: .kitchen-test + allow_failure: true + variables: + KITCHEN_JOB: purge-benchmarks-ubuntu-1804 + +ubuntu-1804-runtime: + extends: .kitchen-test + allow_failure: true + variables: + KITCHEN_JOB: runtime-benchmarks-ubuntu-1804 + +ubuntu-1910-fs: + extends: .kitchen-test + allow_failure: true + variables: + KITCHEN_JOB: filesystem-benchmarks-ubuntu-1910 + +ubuntu-1910-purge: + extends: .kitchen-test + allow_failure: true + variables: + KITCHEN_JOB: purge-benchmarks-ubuntu-1910 + +ubuntu-1910-runtime: + extends: .kitchen-test + allow_failure: true + variables: + KITCHEN_JOB: runtime-benchmarks-ubuntu-1910 diff --git a/.gitlab-ci/Jobs/php_unit_tests.yml b/.gitlab-ci/Jobs/php_unit_tests.yml index 2746c98176..db669e8b48 100644 --- a/.gitlab-ci/Jobs/php_unit_tests.yml +++ b/.gitlab-ci/Jobs/php_unit_tests.yml @@ -46,6 +46,10 @@ artifacts: reports: junit: unitreport.xml + except: + variables: + - $CI_COMMIT_MESSAGE =~ /skip-unit/ + php7.4-mariadb10.4: variables: diff --git a/Berksfile b/Berksfile new file mode 100644 index 0000000000..8da68ac5e7 --- /dev/null +++ b/Berksfile @@ -0,0 +1,5 @@ +source 'https://supermarket.chef.io' + +group :integration do + cookbook 'passbolt_package', path: 'tests/cookbooks/passbolt_package' +end diff --git a/Berksfile.lock b/Berksfile.lock new file mode 100644 index 0000000000..a9526440cb --- /dev/null +++ b/Berksfile.lock @@ -0,0 +1,6 @@ +DEPENDENCIES + passbolt_package + path: tests/cookbooks/passbolt_package + +GRAPH + passbolt_package (0.1.0) diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000000..13650c8c13 --- /dev/null +++ b/Gemfile @@ -0,0 +1,11 @@ +source 'https://rubygems.org' do + gem 'test-kitchen' + gem 'chef' + gem 'berkshelf' + gem 'chef-cli' + gem 'inspec' + gem 'kitchen-inspec' + gem 'kitchen-dokken' + gem 'pry' + gem 'bigdecimal' +end diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000000..690710f004 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,655 @@ +GEM + remote: https://rubygems.org/ + specs: + activesupport (5.2.4.2) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + aws-eventstream (1.1.0) + aws-partitions (1.302.0) + aws-sdk-apigateway (1.38.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-apigatewayv2 (1.19.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-athena (1.24.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-autoscaling (1.22.0) + aws-sdk-core (~> 3, >= 3.52.1) + aws-sigv4 (~> 1.1) + aws-sdk-budgets (1.28.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudformation (1.33.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudhsm (1.20.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudhsmv2 (1.21.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudtrail (1.21.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatch (1.36.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-cloudwatchlogs (1.29.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-codecommit (1.31.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-codedeploy (1.28.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-codepipeline (1.29.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-configservice (1.43.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-core (3.94.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-costandusagereportservice (1.19.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-dynamodb (1.45.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-ec2 (1.154.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecr (1.26.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-ecs (1.60.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-efs (1.26.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-eks (1.35.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticache (1.31.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticbeanstalk (1.28.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticloadbalancing (1.20.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticloadbalancingv2 (1.41.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-elasticsearchservice (1.33.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-firehose (1.26.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-iam (1.36.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-kafka (1.19.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-kinesis (1.21.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-kms (1.30.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-lambda (1.39.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-organizations (1.17.0) + aws-sdk-core (~> 3, >= 3.39.0) + aws-sigv4 (~> 1.0) + aws-sdk-rds (1.83.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-redshift (1.41.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53 (1.32.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53domains (1.20.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-route53resolver (1.12.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.63.0) + aws-sdk-core (~> 3, >= 3.83.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.1) + aws-sdk-securityhub (1.23.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-ses (1.28.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-sms (1.18.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-sns (1.22.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-sqs (1.24.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sdk-ssm (1.73.0) + aws-sdk-core (~> 3, >= 3.71.0) + aws-sigv4 (~> 1.1) + aws-sigv4 (1.1.2) + aws-eventstream (~> 1.0, >= 1.0.2) + azure_graph_rbac (0.17.1) + ms_rest_azure (~> 0.11.0) + azure_mgmt_key_vault (0.17.5) + ms_rest_azure (~> 0.11.1) + azure_mgmt_resources (0.17.8) + ms_rest_azure (~> 0.11.1) + azure_mgmt_security (0.18.0) + ms_rest_azure (~> 0.11.1) + azure_mgmt_storage (0.20.1) + ms_rest_azure (~> 0.11.1) + bcrypt_pbkdf (1.0.1) + berkshelf (7.0.9) + chef (>= 13.6.52) + chef-config + cleanroom (~> 1.0) + concurrent-ruby (~> 1.0) + minitar (>= 0.6) + mixlib-archive (>= 0.4, < 2.0) + mixlib-config (>= 2.2.5) + mixlib-shellout (>= 2.0, < 4.0) + octokit (~> 4.0) + retryable (>= 2.0, < 4.0) + solve (~> 4.0) + thor (>= 0.20) + bigdecimal (2.0.0) + builder (3.2.4) + chef (15.10.12) + addressable + bcrypt_pbkdf (~> 1.0) + bundler (>= 1.10) + chef-config (= 15.10.12) + chef-utils (= 15.10.12) + chef-zero (>= 14.0.11) + diff-lcs (~> 1.2, >= 1.2.4) + ed25519 (~> 1.2) + erubis (~> 2.7) + ffi (~> 1.9, >= 1.9.25) + ffi-libarchive + ffi-yajl (~> 2.2) + highline (>= 1.6.9, < 2) + iniparse (~> 1.4) + license-acceptance (~> 1.0, >= 1.0.5) + mixlib-archive (>= 0.4, < 2.0) + mixlib-authentication (>= 2.1, < 4) + mixlib-cli (>= 2.1.1, < 3.0) + mixlib-log (>= 2.0.3, < 4.0) + mixlib-shellout (>= 3.0.3, < 4.0) + net-sftp (~> 2.1, >= 2.1.2) + net-ssh (>= 4.2, < 6) + net-ssh-multi (~> 1.2, >= 1.2.1) + ohai (~> 15.0) + plist (~> 3.2) + proxifier (~> 1.0) + syslog-logger (~> 1.6) + train-core (~> 3.2, >= 3.2.28) + train-winrm (>= 0.2.5) + tty-screen (~> 0.6) + uuidtools (~> 2.1.5) + chef-cli (2.0.0) + addressable (>= 2.3.5, < 2.6) + chef (>= 14.0) + cookbook-omnifetch (~> 0.5) + diff-lcs (~> 1.0) + ffi-yajl (>= 1.0, < 3.0) + license-acceptance (~> 1.0, >= 1.0.11) + minitar (~> 0.6) + mixlib-cli (>= 1.7, < 3.0) + mixlib-shellout (>= 2.0, < 4.0) + paint (~> 1.0) + solve (> 2.0, < 5.0) + chef-config (15.10.12) + addressable + chef-utils (= 15.10.12) + fuzzyurl + mixlib-config (>= 2.2.12, < 4.0) + mixlib-shellout (>= 2.0, < 4.0) + tomlrb (~> 1.2) + chef-telemetry (1.0.3) + chef-config + concurrent-ruby (~> 1.0) + ffi-yajl (~> 2.2) + http (~> 2.2) + chef-utils (15.10.12) + chef-zero (15.0.0) + ffi-yajl (~> 2.2) + hashie (>= 2.0, < 5.0) + mixlib-log (>= 2.0, < 4.0) + rack (~> 2.0, >= 2.0.6) + uuidtools (~> 2.1) + cleanroom (1.0.0) + coderay (1.1.2) + concurrent-ruby (1.1.6) + cookbook-omnifetch (0.9.1) + mixlib-archive (>= 0.4, < 2.0) + declarative (0.0.10) + declarative-option (0.1.0) + diff-lcs (1.3) + docker-api (1.34.2) + excon (>= 0.47.0) + multi_json + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + ecma-re-validator (0.2.1) + regexp_parser (~> 1.2) + ed25519 (1.2.4) + equatable (0.6.1) + erubi (1.9.0) + erubis (2.7.0) + excon (0.73.0) + faraday (0.17.3) + multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.6) + faraday (>= 0.7.4) + http-cookie (~> 1.0.0) + faraday_middleware (0.12.2) + faraday (>= 0.7.4, < 1.0) + ffi (1.12.2) + ffi-libarchive (1.0.0) + ffi (~> 1.0) + ffi-yajl (2.3.3) + libyajl2 (~> 1.2) + fuzzyurl (0.9.0) + google-api-client (0.34.1) + addressable (~> 2.5, >= 2.5.1) + googleauth (~> 0.9) + httpclient (>= 2.8.1, < 3.0) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.0) + signet (~> 0.12) + googleauth (0.10.0) + faraday (~> 0.12) + jwt (>= 1.4, < 3.0) + memoist (~> 0.16) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (~> 0.12) + gssapi (1.3.0) + ffi (>= 1.0.1) + gyoku (1.3.1) + builder (>= 2.1.2) + hana (1.3.5) + hashie (3.6.0) + highline (1.7.10) + htmlentities (4.3.4) + http (2.2.2) + addressable (~> 2.3) + http-cookie (~> 1.0) + http-form_data (~> 1.0.1) + http_parser.rb (~> 0.6.0) + http-cookie (1.0.3) + domain_name (~> 0.5) + http-form_data (1.0.3) + http_parser.rb (0.6.0) + httpclient (2.8.3) + i18n (1.8.2) + concurrent-ruby (~> 1.0) + inifile (3.0.0) + iniparse (1.5.0) + inspec (4.18.104) + faraday_middleware (~> 0.12.2) + inspec-core (= 4.18.104) + train (~> 3.0) + train-aws (~> 0.1) + train-habitat (~> 0.1) + train-winrm (~> 0.2) + inspec-core (4.18.104) + addressable (~> 2.4) + chef-telemetry (~> 1.0) + faraday (>= 0.9.0) + hashie (~> 3.4) + htmlentities (~> 4.3) + json_schemer (~> 0.2.1) + license-acceptance (>= 0.2.13, < 2.0) + method_source (~> 0.8) + mixlib-log (~> 3.0) + multipart-post (~> 2.0) + parallel (~> 1.9) + parslet (~> 1.5) + pry (~> 0) + rspec (~> 3.9) + rspec-its (~> 1.2) + rubyzip (~> 1.2, >= 1.2.2) + semverse (~> 3.0) + sslshake (~> 1.2) + term-ansicolor (~> 1.7) + thor (>= 0.20, < 2.0) + tomlrb (~> 1.2) + train-core (~> 3.0) + tty-prompt (~> 0.17) + tty-table (~> 0.10) + ipaddress (0.8.3) + jmespath (1.4.0) + json (2.3.0) + json_schemer (0.2.11) + ecma-re-validator (~> 0.2) + hana (~> 1.3) + regexp_parser (~> 1.5) + uri_template (~> 0.7) + jwt (2.2.1) + kitchen-dokken (2.8.2) + docker-api (~> 1.33) + lockfile (~> 2.1) + test-kitchen (>= 1.15, < 3) + kitchen-inspec (1.3.2) + hashie (~> 3.4) + inspec (>= 1.47, < 5.0) + test-kitchen (>= 1.6, < 3) + libyajl2 (1.2.0) + license-acceptance (1.0.19) + pastel (~> 0.7) + tomlrb (~> 1.2) + tty-box (~> 0.3) + tty-prompt (~> 0.18) + little-plugger (1.1.4) + lockfile (2.1.3) + logging (2.2.2) + little-plugger (~> 1.1) + multi_json (~> 1.10) + memoist (0.16.2) + method_source (0.9.2) + mini_mime (1.0.2) + minitar (0.9) + minitest (5.14.0) + mixlib-archive (1.0.5) + mixlib-log + mixlib-authentication (3.0.6) + mixlib-cli (2.1.6) + mixlib-config (3.0.6) + tomlrb + mixlib-install (3.12.1) + mixlib-shellout + mixlib-versioning + thor + mixlib-log (3.0.8) + mixlib-shellout (3.0.9) + mixlib-versioning (1.2.12) + molinillo (0.6.6) + ms_rest (0.7.6) + concurrent-ruby (~> 1.0) + faraday (>= 0.9, < 2.0.0) + timeliness (~> 0.3.10) + ms_rest_azure (0.11.2) + concurrent-ruby (~> 1.0) + faraday (>= 0.9, < 2.0.0) + faraday-cookie_jar (~> 0.0.6) + ms_rest (~> 0.7.6) + unf_ext (= 0.0.7.2) + multi_json (1.14.1) + multipart-post (2.1.1) + necromancer (0.5.1) + net-scp (2.0.0) + net-ssh (>= 2.6.5, < 6.0.0) + net-sftp (2.1.2) + net-ssh (>= 2.6.5) + net-ssh (5.2.0) + net-ssh-gateway (2.0.0) + net-ssh (>= 4.0.0) + net-ssh-multi (1.2.1) + net-ssh (>= 2.6.5) + net-ssh-gateway (>= 1.2.0) + nori (2.6.0) + octokit (4.18.0) + faraday (>= 0.9) + sawyer (~> 0.8.0, >= 0.5.3) + ohai (15.9.1) + chef-config (>= 12.8, < 16) + ffi (~> 1.9) + ffi-yajl (~> 2.2) + ipaddress + mixlib-cli (>= 1.7.0) + mixlib-config (>= 2.0, < 4.0) + mixlib-log (>= 2.0.1, < 4.0) + mixlib-shellout (>= 2.0, < 4.0) + plist (~> 3.1) + systemu (~> 2.6.4) + wmi-lite (~> 1.0) + os (1.1.0) + paint (1.0.1) + parallel (1.19.1) + parslet (1.8.2) + pastel (0.7.3) + equatable (~> 0.6) + tty-color (~> 0.5) + plist (3.5.0) + proxifier (1.0.3) + pry (0.12.2) + coderay (~> 1.1.0) + method_source (~> 0.9.0) + public_suffix (3.1.1) + rack (2.2.2) + regexp_parser (1.7.0) + representable (3.0.4) + declarative (< 0.1.0) + declarative-option (< 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + retryable (3.0.5) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.1) + rspec-support (~> 3.9.1) + rspec-expectations (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-its (1.3.0) + rspec-core (>= 3.0.0) + rspec-expectations (>= 3.0.0) + rspec-mocks (3.9.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.2) + rubyntlm (0.6.2) + rubyzip (1.3.0) + sawyer (0.8.2) + addressable (>= 2.3.5) + faraday (> 0.8, < 2.0) + semverse (3.0.0) + signet (0.14.0) + addressable (~> 2.3) + faraday (>= 0.17.3, < 2.0) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + solve (4.0.3) + molinillo (~> 0.6) + semverse (>= 1.1, < 4.0) + sslshake (1.3.0) + strings (0.1.8) + strings-ansi (~> 0.1) + unicode-display_width (~> 1.5) + unicode_utils (~> 1.4) + strings-ansi (0.2.0) + sync (0.5.0) + syslog-logger (1.6.8) + systemu (2.6.5) + term-ansicolor (1.7.1) + tins (~> 1.0) + test-kitchen (2.4.0) + bcrypt_pbkdf (~> 1.0) + ed25519 (~> 1.2) + license-acceptance (~> 1.0, >= 1.0.11) + mixlib-install (~> 3.6) + mixlib-shellout (>= 1.2, < 4.0) + net-scp (>= 1.1, < 3.0) + net-ssh (>= 2.9, < 6.0) + net-ssh-gateway (>= 1.2, < 3.0) + thor (~> 0.19) + winrm (~> 2.0) + winrm-elevated (~> 1.0) + winrm-fs (~> 1.1) + thor (0.20.3) + thread_safe (0.3.6) + timeliness (0.3.10) + tins (1.24.1) + sync + tomlrb (1.3.0) + train (3.2.28) + activesupport (~> 5.2.3) + azure_graph_rbac (~> 0.16) + azure_mgmt_key_vault (~> 0.17) + azure_mgmt_resources (~> 0.15) + azure_mgmt_security (~> 0.18) + azure_mgmt_storage (~> 0.18) + docker-api (~> 1.26) + google-api-client (>= 0.23.9, < 0.35.0) + googleauth (>= 0.6.6, < 0.11.0) + inifile (~> 3.0) + train-core (= 3.2.28) + train-winrm (~> 0.2) + train-aws (0.1.16) + aws-sdk-apigateway (~> 1.0) + aws-sdk-apigatewayv2 (~> 1.0) + aws-sdk-athena (~> 1.0) + aws-sdk-autoscaling (~> 1.22.0) + aws-sdk-budgets (~> 1.0) + aws-sdk-cloudformation (~> 1.0) + aws-sdk-cloudhsm (~> 1.0) + aws-sdk-cloudhsmv2 (~> 1.0) + aws-sdk-cloudtrail (~> 1.8) + aws-sdk-cloudwatch (~> 1.13) + aws-sdk-cloudwatchlogs (~> 1.13) + aws-sdk-codecommit (~> 1.0) + aws-sdk-codedeploy (~> 1.0) + aws-sdk-codepipeline (~> 1.0) + aws-sdk-configservice (~> 1.21) + aws-sdk-core (~> 3.0) + aws-sdk-costandusagereportservice (~> 1.6) + aws-sdk-dynamodb (~> 1.31) + aws-sdk-ec2 (~> 1.70) + aws-sdk-ecr (~> 1.18) + aws-sdk-ecs (~> 1.30) + aws-sdk-efs (~> 1.0) + aws-sdk-eks (~> 1.9) + aws-sdk-elasticache (~> 1.0) + aws-sdk-elasticbeanstalk (~> 1.0) + aws-sdk-elasticloadbalancing (~> 1.8) + aws-sdk-elasticloadbalancingv2 (~> 1.0) + aws-sdk-elasticsearchservice (~> 1.0) + aws-sdk-firehose (~> 1.0) + aws-sdk-iam (~> 1.13) + aws-sdk-kafka (~> 1.0) + aws-sdk-kinesis (~> 1.0) + aws-sdk-kms (~> 1.13) + aws-sdk-lambda (~> 1.0) + aws-sdk-organizations (~> 1.17.0) + aws-sdk-rds (~> 1.43) + aws-sdk-redshift (~> 1.0) + aws-sdk-route53 (~> 1.0) + aws-sdk-route53domains (~> 1.0) + aws-sdk-route53resolver (~> 1.0) + aws-sdk-s3 (~> 1.30) + aws-sdk-securityhub (~> 1.0) + aws-sdk-ses (~> 1.0) + aws-sdk-sms (~> 1.0) + aws-sdk-sns (~> 1.9) + aws-sdk-sqs (~> 1.10) + aws-sdk-ssm (~> 1.0) + train-core (3.2.28) + addressable (~> 2.5) + json (>= 1.8, < 3.0) + mixlib-shellout (>= 2.0, < 4.0) + net-scp (>= 1.2, < 3.0) + net-ssh (>= 2.9, < 6.0) + train-habitat (0.2.13) + train-winrm (0.2.6) + winrm (~> 2.0) + winrm-fs (~> 1.0) + tty-box (0.5.0) + pastel (~> 0.7.2) + strings (~> 0.1.6) + tty-cursor (~> 0.7) + tty-color (0.5.1) + tty-cursor (0.7.1) + tty-prompt (0.21.0) + necromancer (~> 0.5.0) + pastel (~> 0.7.0) + tty-reader (~> 0.7.0) + tty-reader (0.7.0) + tty-cursor (~> 0.7) + tty-screen (~> 0.7) + wisper (~> 2.0.0) + tty-screen (0.7.1) + tty-table (0.11.0) + equatable (~> 0.6) + necromancer (~> 0.5) + pastel (~> 0.7.2) + strings (~> 0.1.5) + tty-screen (~> 0.7) + tzinfo (1.2.7) + thread_safe (~> 0.1) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.2) + unicode-display_width (1.7.0) + unicode_utils (1.4.0) + uri_template (0.7.0) + uuidtools (2.1.5) + winrm (2.3.4) + builder (>= 2.1.2) + erubi (~> 1.8) + gssapi (~> 1.2) + gyoku (~> 1.0) + httpclient (~> 2.2, >= 2.2.0.2) + logging (>= 1.6.1, < 3.0) + nori (~> 2.0) + rubyntlm (~> 0.6.0, >= 0.6.1) + winrm-elevated (1.2.1) + erubi (~> 1.8) + winrm (~> 2.0) + winrm-fs (~> 1.0) + winrm-fs (1.3.3) + erubi (~> 1.8) + logging (>= 1.6.1, < 3.0) + rubyzip (~> 1.1) + winrm (~> 2.0) + wisper (2.0.1) + wmi-lite (1.0.5) + +PLATFORMS + ruby + +DEPENDENCIES + berkshelf! + bigdecimal! + chef! + chef-cli! + inspec! + kitchen-dokken! + kitchen-inspec! + pry! + test-kitchen! + +BUNDLED WITH + 2.1.2 diff --git a/chefignore b/chefignore new file mode 100644 index 0000000000..7be3c6dfaf --- /dev/null +++ b/chefignore @@ -0,0 +1 @@ +.kitchen diff --git a/debian/README.debian.md b/debian/README.debian.md new file mode 100644 index 0000000000..83afbab295 --- /dev/null +++ b/debian/README.debian.md @@ -0,0 +1,130 @@ +# Passbolt Debian package + +## Requirements + +- Debian environment +- Packages: devscripts, build-essential, fakeroot, equivs, cdbs +- Vendor packages installed + +### Install vendor packages + + +``` +$ composer install --no-dev -o --prefer-dist --no-interaction +``` + +Install vendor packages through a container: + +``` +$ docker run -ti "${PWD}":/app composer install --no-dev -o --prefer-dist --ignore-platform-reqs +``` + +### Install build dependencies + +``` +sudo apt-get install devscripts build-essential fakeroot equivs cdbs +``` + +## Build process + +``` +$ sudo mk-build-deps -irt'apt-get --no-install-recommends -yV' debian/control && dpkg-checkbuilddeps +$ debuild -us -uc -b +``` + +The package should become available at the parent directory as passbolt-@PASSBOLT_FLAVOUR@-server_*deb. +To install it locally, use `apt-get install ./passbolt-*.deb`. + +After installation, you should be able to point your browser to `http://localhost` +and follow the Web based configuration pages to get Passbolt up and running. + +Removing the package is best accomplished with "apt-get purge passbolt-@PASSBOLT_FLAVOUR@-server", which will remove all the software +along with configuration files and other sensitive information. `apt-get remove` will only delete +binary files, but because passbolt is basically php code, it will not remove most files from the system. + +## Testing + +This package comes with a testing suite based on the automation framework kitchenci and +the infra testing framework inspec. Both tools are ruby based. + +### Requirements + +It is possible to run the whole testing environment from a docker container without having to install +any ruby dependency locally. For the sake of completeness we will describe the docker option and the native +installation. + +#### Run test inside a docker container + +##### Requirements + +- Docker engine installed +- Passbolt vendors installed (See this readme section "Install vendor packages") + +##### Testing execution + +In order to run the tests you must mount a few paths from your host into the container: + +- The docker.sock (Linux: /var/run/docker.sock) +- The docker lib dir (Linux: /var/lib/docker) +- Your user home +- /etc/passwd (To map your user to the container to avoid permission problems) +- /etc/group (Same as above) +- A directory to persist the bundle dependency installation so it does not download all the deps every time + +Example run: + +``` +$ docker run -ti -v "${PWD}":/app \ + -u "$(id -u ${USER}):$(id -u ${USER})" \ + composer /bin/bash -c "composer global require hirak/prestissimo \ + composer install -o --prefer-dist --no-dev --ignore-platform-reqs" +$ docker run -ti -v :/var/run/docker.sock \ + -v /home/:/home/ \ + -u "$(id -u ${USER}):" \ + -v /etc/passwd:/etc/passwd:ro \ + -v /etc/group:/etc/group:ro \ + chef/chefdk:latest bash +``` + +Once in the container navigate to the code diretory. As the home folder from the host is mounted +the code should be in a directory which is known to you. + +To run test in isolation (create dependencies, run tests, destroy dependencies): + +``` +$ cd /home/the/passbolt/repo +$ gem install bundle:2.1.2 +$ kitchen list # This will show which tests and on which platforms you can run them +$ kitchen test filesystem-benchmarks-debian-buster -t tests/integration # Example test run +``` + +To install dependencies and run tests (without destroying the container): + +``` +$ cd /home/the/passbolt/repo +$ kitchen converge filesystem-benchmarks-debian-buster # This installs all the required deps to run the tests +$ kitchen verify filesystem-benchmarks-debian-buster # Runs the tests without destroying infra after +``` + +#### Run test from the host + +##### Requirements + +- ruby installed +- bundler installed + +In order to run the tests: + +``` +$ bundle install +$ bundle exec kitchen list # This will show which tests and on which platforms you can run them +$ bundle exec kitchen test filesystem-benchmarks-debian-buster -t tests/integration # Example test run +``` + +Or: + +``` +$ bundle install +$ bundle exec kitchen converge filesystem-benchmarks-debian-buster # This installs all the required deps to run the tests +$ bundle exec kitchen verify filesystem-benchmarks-debian-buster # Runs the tests without destroying infra after +``` diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000000..d40595c858 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,24 @@ +passbolt-pro-server (2.12.0-1) stretch; urgency=medium + * Refactor config script + * Refactor postinst script + * Added questions for nginx setup + * Wording on the templates file + * Cleaned git files from build + * Added .in templates for multiple build files + * Added lintian overrides + * Added logrotation for /var/log/passbolt/error.log + * Introduced triggers for mysql and nginx + + -- Diego Lendoiro Thu, 21 May 2020 18:24:00 +0000 + +passbolt-pro-server (2.12.0-0) stretch; urgency=medium + + * Created an automated debian package + + -- Albert Casals Fri, 27 Dec 2019 01:15:00 +0100 + +passbolt-pro-server (2.7.1-0) stretch; urgency=medium + + * Initial release. + + -- Diego Lendoiro Fri, 8 Mar 2019 10:08:11 +0000 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000000..f599e28b8a --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +10 diff --git a/debian/conf/nginx-passbolt-ssl.conf b/debian/conf/nginx-passbolt-ssl.conf new file mode 100644 index 0000000000..5386e51f80 --- /dev/null +++ b/debian/conf/nginx-passbolt-ssl.conf @@ -0,0 +1,20 @@ +# +# nginx-passbolt.conf +# +# Passbolt provided file to be included from nginx main virtual hosts file. +# It allows to pull common SSL settings from a central place. +# +# Use the nginx include directive to pull this information in. +# + + # Managed by Passbolt + ssl on; + ssl_certificate __CERT_PATH__ + ssl_certificate_key __KEY_PATH__ + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_prefer_server_ciphers on; + + ssl_ciphers "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:@STRENGTH"; + + ssl_session_tickets off; diff --git a/debian/conf/nginx-passbolt.conf b/debian/conf/nginx-passbolt.conf new file mode 100644 index 0000000000..ae36b20bb1 --- /dev/null +++ b/debian/conf/nginx-passbolt.conf @@ -0,0 +1,45 @@ +# +# Passbolt.conf - Nginx configuration file to run the Passbolt software. +# + +server { + + listen 80; + + # Managed by Passbolt + # server_name + + client_body_buffer_size 100K; + client_header_buffer_size 1K; + client_max_body_size 5M; + + client_body_timeout 10; + client_header_timeout 10; + keepalive_timeout 5 5; + send_timeout 10; + + root /usr/share/php/passbolt/webroot; + index index.php; + error_log /var/log/nginx/passbolt-error.log info; + access_log /var/log/nginx/passbolt-access.log; + + # Managed by Passbolt + # include __PASSBOLT_SSL__ + + location / { + try_files $uri $uri/ /index.php?$args; + } + + location ~ \.php$ { + try_files $uri =404; + include fastcgi_params; + fastcgi_pass unix:/run/php/__PHP_VERSION__-fpm.sock; + fastcgi_index index.php; + fastcgi_intercept_errors on; + fastcgi_split_path_info ^(.+\.php)(.+)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SERVER_NAME $http_host; + fastcgi_param PHP_VALUE "upload_max_filesize=5M \n post_max_size=5M"; + } + +} diff --git a/debian/config b/debian/config new file mode 100755 index 0000000000..c2f4241980 --- /dev/null +++ b/debian/config @@ -0,0 +1,310 @@ +#!/bin/bash +# +# Debconf config script file. +# +# The config script is responsible for asking any questions +# necessary to configure the package. +# + +. /usr/share/debconf/confmodule + +db_version 2.0 + +deb_action=$1 +deb_version=$2 + + +######################################## +# Helper functions +######################################## + +_echo() { + [ -z "${VERBOSE}" ] || echo ">>> $1" +} + +# +# is_interactive() +# +# Returns 1 if last db_input command was interactive +# 0 otherwise, meaning noninteractive frontend. +# +is_interactive() { + rc=$? + [ "$rc" != "30" ] && return 0 + return 1 +} + + +blank_string() { + local string="$1" + + if [ -z "$string" ]; then + return 0 + fi + return 1 +} + +invalid_characters() { + local string="$1" + + if [[ "$string" =~ .*-.*|.*' '.* ]]; then + return 0 + fi + + return 1 +} + +######################################## +# Password related validation functions +######################################## + +password_verify() { + local password="$1" + local verification="$2" + + if [ "$password" != "$verification" ]; then + return 1 + fi + return 0 +} + + +########################################### +# Database setup functions +########################################### + +db_name_validator() { + local db_name="$1" + + if blank_string "$db_name" || invalid_characters "$db_name"; then + return 1 + fi + + return 0 +} + +db_name_validation() { + local db_name="" + + db_get passbolt/mysql-passbolt-dbname + db_name="$RET" + while ! db_name_validator "$db_name" + do + db_set passbolt/mysql-passbolt-dbname "" + db_input high passbolt/db_invalid_characters || true + db_input high passbolt/mysql-passbolt-dbname || true + db_go || true + db_get passbolt/mysql-passbolt-dbname + db_name="$RET" + done +} + +db_password_validation() { + local password='' + local verification='_UNDEF_' + + while ! password_verify "$password" "$verification" + do + db_get passbolt/mysql-passbolt-password + password="$RET" + if blank_string "$password"; then + db_input high passbolt/non-empty-password || true + db_input high passbolt/mysql-passbolt-password || true + db_go || true + else + db_input high passbolt/mysql-passbolt-password-repeat || true + db_go || true + db_get passbolt/mysql-passbolt-password-repeat + verification="$RET" + if ! password_verify "$password" "$verification"; then + db_input high passbolt/non-matching-passwords || true + db_input high passbolt/mysql-passbolt-password || true + db_go || true + fi + fi + done +} + +get_admin_credentials() { + db_input high passbolt/mysql-username || true + db_input high passbolt/mysql-password || true +} + +get_user_credentials() { + db_input high passbolt/mysql-passbolt-username || true + db_input high passbolt/mysql-passbolt-password + if is_interactive; then + db_go || true + db_password_validation + fi +} + +get_database_name() { + db_input high passbolt/mysql-passbolt-dbname + if is_interactive; then + db_go || true + db_name_validation + fi +} + +database_setup() { + db_input high passbolt/mysql-configuration || true + db_go || true + db_get passbolt/mysql-configuration + enable_mysql_conf=$RET + + if [ "$enable_mysql_conf" == true ]; then + get_admin_credentials + get_user_credentials + get_database_name + fi +} + + +########################################### +# Domain setup functions +########################################### + +# +# hostname_validation() +# +# Validates the domain syntax in the form example.com +# Returns 0 if domain is correct, 1 if malformed. +# Empty string is accepted as correct. +# IP addresses are also considerect correct +hostname_validation() { + local host="$1" + + if ! [[ "$host" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ || \ + "$host" =~ ^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}$ || \ + -z "$host" ]]; then + return 1 + else + return 0 + fi +} + +get_domain() { + local validated=0 + + while [ "$validated" == "0" ]; do + db_input high passbolt/nginx-domain || true + if is_interactive; then + db_go || true + db_get passbolt/nginx-domain + if ! hostname_validation "$RET"; then + db_input high passbolt/nginx-domain-incorrect || true + db_go || true + else + validated=1 + fi + else + validated=1 + fi + done +} + +########################################### +# SSL setup functions +########################################### + +get_ssl_path() { + local template="$1" + + db_input high passbolt/"${template}" || true + db_go || true + db_get passbolt/"${template}" +} + +ssl_cert_validation() { + local path='_UNDEF_' + local cert_type="$1" + + get_ssl_path "nginx-${cert_type}-file" + path="$RET" + + while [ ! -f "$path" ] + do + db_set passbolt/nginx-"${cert_type}"-file "" + get_ssl_path "${cert_type}-file-not-found" + get_ssl_path "nginx-${cert_type}-file" + path="$RET" + done +} + +ssl_manual_setup() { + ssl_cert_validation 'certificate' + ssl_cert_validation 'certificate-key' +} + +get_ssl_conf_mode() { + local mode="$1" + + case "$mode" in + "manual") + ssl_manual_setup + ;; + "auto") + db_input high passbolt/nginx-letsencrypt-email || true + ;; + "none") + ;; + *) + echo "WARNING: Invalid Passbolt configuration mode: $mode" + exit 1 + ;; + esac + db_go || true +} + +########################################### +# Nginx setup functions +########################################### + +get_nginx_conf_mode() { + if [ -x "$(command -v certbot)" ]; then + db_input high passbolt/nginx-configuration-three-choices || true + db_go || true + db_set passbolt/nginx-configuration-two-choices "" + db_get passbolt/nginx-configuration-three-choices + else + db_input high passbolt/nginx-configuration-two-choices || true + db_go || true + db_set passbolt/nginx-configuration-three-choices "" + db_get passbolt/nginx-configuration-two-choices + fi +} + +nginx_setup() { + db_input high passbolt/nginx-configuration || true + db_go || true + db_get passbolt/nginx-configuration + enable_nginx_conf=$RET + + if [ "$enable_nginx_conf" == true ]; then + get_nginx_conf_mode + nginx_conf_mode="$RET" + + get_domain + get_ssl_conf_mode "$nginx_conf_mode" + fi +} + + +########################################### +# Script starts here +########################################### + +_echo "entering config script: action=$deb_action version=$deb_version" + +if [[ ( "${deb_action}" == "reconfigure" ) || \ + ( "${deb_action}" == "configure" && "${deb_version}" == "" ) ]]; then + + # On interactive installs, we want debconf dialogs only when: + # installing for the first time + # dpkg-reconfigure package + database_setup + nginx_setup +else + _echo "config to upgrade from version: $deb_version, nothing to do" +fi diff --git a/debian/control b/debian/control new file mode 100644 index 0000000000..502811c623 --- /dev/null +++ b/debian/control @@ -0,0 +1,29 @@ +Source: passbolt-api-common +Maintainer: Passbolt SA +Section: php +Priority: optional +Standards-Version: 4.1.3 +Build-Depends: debhelper (>= 10), dh-exec +Homepage: https://www.passbolt.com +Vcs-Git: git@github.com:passbolt/passbolt-api.git + +Package: passbolt-api-common +Architecture: all +Pre-depends: + debconf +Depends: ${misc:Depends}, + php-cli (>= 7), + php-mbstring (>= 7), + php-intl (>= 7), + php-mysql (>= 7), + php-fpm (>= 7), + php-xml (>= 7), + php-gd (>= 7), + php-gnupg, + cron +Recommends: default-mysql-server | virtual-mysql-server, nginx | apache2 +Suggests: certbot, python-certbot-nginx | python-certbot-apache +Description: Passbolt, open source password manager for teams + Passbolt is a free and open source password manager + designed for collaboration. It allows team members to store and share + credentials securely. diff --git a/debian/control.in b/debian/control.in new file mode 100644 index 0000000000..14e882611b --- /dev/null +++ b/debian/control.in @@ -0,0 +1,30 @@ +Source: passbolt-@PASSBOLT_FLAVOUR@-server +Maintainer: Passbolt SA +Section: php +Priority: optional +Standards-Version: 4.1.3 +Build-Depends: debhelper (>= 10), dh-exec +Homepage: https://www.passbolt.com +Vcs-Git: git@github.com:passbolt/passbolt-api.git + +Package: passbolt-@PASSBOLT_FLAVOUR@-server +Architecture: all +Pre-depends: + debconf +Depends: ${misc:Depends}, + php-cli (>= 7), + php-mbstring (>= 7), + php-intl (>= 7), + php-mysql (>= 7), + php-fpm (>= 7), + php-xml (>= 7), + php-gd (>= 7), + @PASSBOLT_EXTENSIONS@ + php-gnupg, + cron +Recommends: default-mysql-server | virtual-mysql-server, nginx | apache2 +Suggests: certbot, python-certbot-nginx | python-certbot-apache +Description: Passbolt, open source password manager for teams + Passbolt is a free and open source password manager + designed for collaboration. It allows team members to store and share + credentials securely. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000000..01ded932ee --- /dev/null +++ b/debian/copyright @@ -0,0 +1,133 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: passbolt_api +Source: https://github.com/passbolt/passbolt_api + +Files: * +Copyright: 2015-2016 Bolt Softwares Pvt. Ltd. + 2017-2018 Passbolt SARL + 2019 Passbolt SA +License: AGPL-3 + +Files: vendor/aura/* +Copyright: Copyright (c) 2017, Aura for PHP +License: MIT + +Files: vendor/burzum/cakephp-imagine-plugin/* +Copyright: Copyright 2012 - 2014, Florian Krämer +License: MIT + +Files: vendor/burzum/file-storage/* +Copyright: Copyright (C) 2012 - 2014 by Florian Krämer +License: public-domain + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Files: vendor/cakephp/cakephp/* +Copyright: Copyright (c) 2005-2018, Cake Software Foundation, Inc. (https://cakefoundation.org) +License: MIT + +Files: vendor/cakephp/chronos/* +Copyright:Copyright (C) Cake Software Foundation, Inc. (http://cakefoundation.org) +License: public-domain + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Files: vendor/cakephp/migrations/* +Copyright: Copyright (c) 2005-2016, Cake Software Foundation, Inc. +License: MIT + +Files: vendor/cakephp/plugin-installer/* +Copyright: Copyright (c) 2005-2015, Cake Software Foundation, Inc. +License: MIT + +Files: vendor/composer/* +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano +License: Expat + +Files: vendor/composer/src/Composer/Util/TlsHelper.php +Copyright: 2016, Nils Adermann + 2016, Jordi Boggiano + 2013, Evan Coury +License: Expat and BSD-2-Clause + +License: BSD-2-Clause + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + . + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + . + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: Expat + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + +Files: vendor/donatj/phpuseragentparser/* +Copyright: Copyright (c) 2013 Jesse G. Donat +License: MIT + +Files: vendor/ezyang/htmlpurifier/* +Copyright: Edward Z. Yang +License: /usr/share/common-licenses/LGPL diff --git a/debian/cron.d.in b/debian/cron.d.in new file mode 100644 index 0000000000..50d7eb458b --- /dev/null +++ b/debian/cron.d.in @@ -0,0 +1,12 @@ +# +# +# Cronjob to process emails for the Passbolt Web Service every minute. +# +# This crontab script is part of the Passbolt Debian package, +# see dh_installcron debhelper program for more details. +# + +PATH=/bin:/usr/local/bin:/usr/bin +PASSBOLT_BASE_DIR=/usr/share/php/passbolt + +* * * * * www-data $PASSBOLT_BASE_DIR/bin/cake EmailQueue.sender diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000000..3423fa5024 --- /dev/null +++ b/debian/dirs @@ -0,0 +1,4 @@ +/var/log/passbolt +/var/lib/passbolt/.gnupg +/etc/passbolt/gpg +/var/lib/passbolt/tmp diff --git a/debian/docs.in b/debian/docs.in new file mode 100644 index 0000000000..443a0a42a0 --- /dev/null +++ b/debian/docs.in @@ -0,0 +1,2 @@ +README.md +LICENSE.txt diff --git a/debian/install b/debian/install new file mode 100755 index 0000000000..020301812c --- /dev/null +++ b/debian/install @@ -0,0 +1,19 @@ +#!/usr/bin/dh-exec + +src/* usr/share/php/passbolt/src/ +bin/cake* usr/share/php/passbolt/bin/ + +config/*php etc/passbolt/ +config/Migrations etc/passbolt/ +config/schema etc/passbolt/ +config/app.default.php => etc/passbolt/app.php + +plugins/* usr/share/php/passbolt/plugins/ + +webroot/* usr/share/php/passbolt/webroot/ +vendor/* usr/share/php/passbolt/vendor/ + +index.php usr/share/php/passbolt/ +.htaccess usr/share/php/passbolt/ + +debian/conf/* usr/share/passbolt/examples diff --git a/debian/lintian-overrides.in b/debian/lintian-overrides.in new file mode 100644 index 0000000000..3fb895c13b --- /dev/null +++ b/debian/lintian-overrides.in @@ -0,0 +1,4 @@ +# we prefer etc/passbolt to not be readable for others +non-standard-dir-perm etc/passbolt/* 0770 != 0755 +# Files inside etc/passbolt are not readable for others +non-standard-file-perm etc/passbolt/* 0640 != 0644 diff --git a/debian/logrotate.in b/debian/logrotate.in new file mode 100644 index 0000000000..0b00ad12f1 --- /dev/null +++ b/debian/logrotate.in @@ -0,0 +1,9 @@ +/var/log/passbolt/error.log { + daily + missingok + rotate 14 + compress + delaycompress + notifempty + create 0640 www-data www-data +} diff --git a/debian/patches/01_paths_setup.patch b/debian/patches/01_paths_setup.patch new file mode 100644 index 0000000000..4d33dc7705 --- /dev/null +++ b/debian/patches/01_paths_setup.patch @@ -0,0 +1,80 @@ +Index: passbolt-@PASSBOLT_FLAVOUR@-server/bin/cake.php +=================================================================== +--- passbolt-@PASSBOLT_FLAVOUR@-server.orig/bin/cake.php ++++ passbolt-@PASSBOLT_FLAVOUR@-server/bin/cake.php +@@ -3,6 +3,8 @@ + // Check platform requirements + require dirname(__DIR__) . '/config/requirements.php'; + require dirname(__DIR__) . '/vendor/autoload.php'; ++include '/etc/passbolt/bootstrap.php'; ++ + use App\Application; + use Cake\Console\CommandRunner; + // Build the runner with an application and root executable name. +Index: passbolt-@PASSBOLT_FLAVOUR@-server/config/default.php +=================================================================== +--- passbolt-@PASSBOLT_FLAVOUR@-server.orig/config/default.php ++++ passbolt-@PASSBOLT_FLAVOUR@-server/config/default.php +@@ -138,10 +138,10 @@ return [ + // - Apache on Debian it would be in '/var/www/.gnupg' + // - Nginx on Centos it would be in '/var/lib/nginx/.gnupg' + // - etc. +- 'keyring' => getenv("HOME") . DS . '.gnupg', ++ 'keyring' => '/var/lib/passbolt' . DS . '.gnupg', + + // Replace GNUPGHOME with above value even if it is set. +- 'putenv' => false, ++ 'putenv' => true, + + // Main server key. + 'serverKey' => [ +Index: passbolt-@PASSBOLT_FLAVOUR@-server/config/paths.php +=================================================================== +--- passbolt-@PASSBOLT_FLAVOUR@-server.orig/config/paths.php ++++ passbolt-@PASSBOLT_FLAVOUR@-server/config/paths.php +@@ -28,7 +28,7 @@ if (!defined('DS')) { + /** + * The full path to the directory which holds "src", WITHOUT a trailing DS. + */ +-define('ROOT', dirname(__DIR__)); ++define('ROOT', '/usr/share/php/passbolt'); + + /** + * The actual directory name for the application directory. Normally +@@ -44,7 +44,7 @@ define('APP', ROOT . DS . APP_DIR . DS); + /** + * Path to the config directory. + */ +-define('CONFIG', ROOT . DS . 'config' . DS); ++define('CONFIG', '/etc/passbolt' . DS); + + /** + * File path to the webroot directory. +@@ -69,12 +69,12 @@ define('FIXTURES', TESTS . 'Fixture' . D + /** + * Path to the temporary files directory. + */ +-define('TMP', ROOT . DS . 'tmp' . DS); ++define('TMP', '/var/lib/passbolt/tmp' . DS); + + /** + * Path to the logs directory. + */ +-define('LOGS', ROOT . DS . 'logs' . DS); ++define('LOGS', '/var/log/passbolt' . DS); + + /** + * Path to the cache files directory. It can be shared between hosts in a multi-server setup. +Index: passbolt-@PASSBOLT_FLAVOUR@-server/webroot/index.php +=================================================================== +--- passbolt-@PASSBOLT_FLAVOUR@-server.orig/webroot/index.php ++++ passbolt-@PASSBOLT_FLAVOUR@-server/webroot/index.php +@@ -32,7 +32,7 @@ use App\Application; + use Cake\Http\Server; + + // Bind your application to the server. +-$server = new Server(new Application(dirname(__DIR__) . '/config')); ++$server = new Server(new Application('/etc/passbolt')); + + // Run the request/response through the application + // and emit the response. diff --git a/debian/patches/02_webpaths_setup.patch b/debian/patches/02_webpaths_setup.patch new file mode 100644 index 0000000000..c1f567f8b3 --- /dev/null +++ b/debian/patches/02_webpaths_setup.patch @@ -0,0 +1,13 @@ +Index: passbolt-@PASSBOLT_FLAVOUR@-server/webroot/index.php +=================================================================== +--- passbolt-@PASSBOLT_FLAVOUR@-server.orig/webroot/index.php ++++ passbolt-@PASSBOLT_FLAVOUR@-server/webroot/index.php +@@ -14,7 +14,7 @@ + * @since 0.2.9 + * @license MIT License (http://www.opensource.org/licenses/mit-license.php) + */ +-require dirname(__DIR__) . '/config/requirements.php'; ++include '/etc/passbolt/requirements.php'; + + // for built-in server + if (php_sapi_name() === 'cli-server') { diff --git a/debian/patches/03_cake_import_paths.patch b/debian/patches/03_cake_import_paths.patch new file mode 100644 index 0000000000..cdc0afbd5b --- /dev/null +++ b/debian/patches/03_cake_import_paths.patch @@ -0,0 +1,19 @@ +--- a/bin/cake.php ++++ b/bin/cake.php +@@ -1,12 +1,12 @@ + #!/usr/bin/php -q + run($argv)); +\ No newline at end of file ++$runner = new CommandRunner(new Application('/etc/passbolt'), 'cake'); ++exit($runner->run($argv)); diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000000..990cd5af88 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,3 @@ +02_webpaths_setup.patch +01_paths_setup.patch +03_cake_import_paths.patch diff --git a/debian/postinst b/debian/postinst new file mode 100755 index 0000000000..df32a82c79 --- /dev/null +++ b/debian/postinst @@ -0,0 +1,275 @@ +#!/bin/bash +# +# postinst +# +# Debian package post installation script +# +# The configure step below covers both initial package installation, +# *as well as* upgrades from version x.y to x.z. +# +# For specific tasks during an upgrade, see postrm script, "upgrade" step. +# +# To display response variables for debugging the installation: +# + +set -e + +. /usr/share/debconf/confmodule + +db_version 2.0 + +# Parameters passed from apt install +deb_action=$1 +deb_version=$2 + +current_version=$(dpkg-query --show --showformat='${Version}' passbolt-@PASSBOLT_FLAVOUR@-server) + +# Array variables set by get_* functions +declare -A sql_values +declare -A nginx_values + +# We want to extract php version in the form: "php7.x" +PHP_MAJOR_MINOR="$(php -r "echo PHP_VERSION;" | sed 's:\(7\.[0-3]\).*:\1:')" +PHP_VERSION="php${PHP_MAJOR_MINOR}" + +NGINX_CONF_EXAMPLE="/usr/share/passbolt/examples/nginx-passbolt.conf" +NGINX_SSL_EXAMPLE="/usr/share/passbolt/examples/nginx-passbolt-ssl.conf" +NGINX_CONF="/etc/nginx/sites-enabled/nginx-passbolt.conf" +NGINX_SSL="/etc/passbolt/nginx-ssl.conf" +NGINX_SITES_AVAILABLE="/etc/nginx/sites-available" +NGINX_SITES_ENABLED="/etc/nginx/sites-enabled" +PASSBOLT_SSL_CERT_PATH="/etc/ssl/certs" +PASSBOLT_SSL_KEY_PATH="/etc/ssl/private" + +########################################### +# Functions to debug debconf responses +########################################### + +_echo() { + [ -z "${VERBOSE}" ] || echo ">>> $1" +} + +debug_mysql_values() { + _echo "sql values:" + for i in "${!sql_values[@]}"; do + _echo " ${i}=${sql_values[$i]}" + done +} + +debug_nginx_values() { + _echo "nginx values:" + for i in "${!nginx_values[@]}"; do + _echo " ${i}=${nginx_values[$i]}" + done +} + + +########################################### +# Functions to get debconf response values +########################################### + +get_mysql_values() { + + db_get passbolt/mysql-configuration + sql_values[configuration]=$RET + db_get passbolt/mysql-username + sql_values[db_username]=$RET + db_get passbolt/mysql-password + sql_values[db_password]=$RET + + db_get passbolt/mysql-passbolt-username + sql_values[db_passbolt_username]=$RET + db_get passbolt/mysql-passbolt-password + sql_values[db_passbolt_password]=$RET + db_get passbolt/mysql-passbolt-dbname + sql_values[db_passbolt_dbname]=$RET +} + +get_nginx_values() { + db_get passbolt/nginx-configuration-three-choices + value=$RET + if [ "$value" == "" ]; then + db_get passbolt/nginx-configuration-two-choices + value=$RET + else + db_set passbolt/nginx-configuration-two-choices "" + fi + nginx_values[configuration]=$value + + # assign domain name, set "_" catch-all if empty + db_get passbolt/nginx-domain + nginx_values[domain]="${RET:-_}" + + db_get passbolt/nginx-letsencrypt-email + nginx_values[letsencrypt_email]=$RET + db_get passbolt/nginx-certificate-file + nginx_values[cert_file]=$RET + db_get passbolt/nginx-certificate-key-file + nginx_values[cert_key_file]=$RET +} + + +########################################### +# Functions to run Passbolt migrations +########################################### + +is_upgrade() { + # Returns 0 if we are running a package upgrade, 1 otherwise. + if [[ "${deb_action}" == "configure" && \ + ("${deb_version}" == "$current_version" || "${deb_version}" == "" ) ]]; then + return 1 + fi + return 0 +} + +run_migrations() { + # Migrations are running as the superuser + _echo "running Passbolt migrations steps" + /usr/share/php/passbolt/bin/cake passbolt migrate +} + + +########################################### +# Functions to configure mysql +########################################### + +configure_mysql() { + + # Sanity check: Do not accept empty data for mysql setup. + # This could be specially confusing with automated installs and reconfigures. + if [[ "${sql_values[db_passbolt_username]}" == "" || \ + "${sql_values[db_passbolt_dbname]}" == "" || \ + "${sql_values[db_passbolt_password]}" == "" ]]; then + + echo "WARNING: Passbolt is missing mysql responses: check username, dbname and password" + return + fi + + # Create the Passbolt Database and Username; Grant all access to new user + MYSQL="mysql -u${sql_values[db_username]} -e " + if [ "${sql_values[db_password]}" != "" ]; then + MYSQL="mysql -u${sql_values[db_username]} -p${sql_values[db_password]} -e " + fi + + $MYSQL "CREATE DATABASE IF NOT EXISTS ${sql_values[db_passbolt_dbname]} \ + DEFAULT CHARACTER SET utf8 COLLATE utf8_bin ;" + + $MYSQL "CREATE USER IF NOT EXISTS '${sql_values[db_passbolt_username]}'@'127.0.0.1' \ + IDENTIFIED BY '${sql_values[db_passbolt_password]}' ;" + + $MYSQL "GRANT ALL PRIVILEGES ON ${sql_values[db_passbolt_dbname]}.* \ + TO '${sql_values[db_passbolt_username]}'@'127.0.0.1' ;" +} + + +########################################### +# Functions to configure nginx +########################################### + +configure_nginx_config_file() { + if [ -d "$NGINX_SITES_AVAILABLE" ] && [ -d "$NGINX_SITES_ENABLED" ]; then + _echo "nginx: activating http configuration file" + + # install passbolt virtual host configuration + cp $NGINX_CONF_EXAMPLE "$NGINX_SITES_AVAILABLE" + ln -sf "$NGINX_SITES_AVAILABLE/nginx-passbolt.conf" "$NGINX_SITES_ENABLED/" + sed -i "s/# server_name/server_name ${nginx_values[domain]};/g" $NGINX_CONF + sed -i "s/__PHP_VERSION__/$PHP_VERSION/g" $NGINX_CONF + fi +} + +configure_nginx_local_certs() { + configure_nginx_config_file + _echo "nginx: activating https with local certificates" + + # copy user certificate files to local passbolt namespace + cp "${nginx_values[cert_file]}" "$PASSBOLT_SSL_CERT_PATH" + cp "${nginx_values[cert_key_file]}" "$PASSBOLT_SSL_KEY_PATH" + + # copy nginx https sample configuration for ssl options + cp "$NGINX_SSL_EXAMPLE" "$NGINX_SSL" + + # replace paths to pull from the locally copied files + local_cert_file="${PASSBOLT_SSL_CERT_PATH}/$(basename "${nginx_values[cert_file]}")" + local_cert_key_file="${PASSBOLT_SSL_KEY_PATH}/$(basename "${nginx_values[cert_key_file]}")" + + # apply changes to nginx virtual host file, and ssl include file + sed -i "s|listen 80;|listen 443;|g" "$NGINX_CONF" + sed -i "s|# include __PASSBOLT_SSL__|include ${NGINX_SSL};|g" "$NGINX_CONF" + sed -i "s|ssl_certificate __CERT_PATH__|ssl_certificate ${local_cert_file};|g" "$NGINX_SSL" + sed -i "s|ssl_certificate_key __KEY_PATH__|ssl_certificate_key ${local_cert_key_file};|g" "$NGINX_SSL" +} + +configure_nginx_letsencrypt() { + configure_nginx_config_file + _echo "nginx: activating https via letsencrypt" + + # Certbot will generate the certificate and edit nginx config for us + certbot --agree-tos --non-interactive \ + --nginx -m "${nginx_values[letsencrypt_email]}" \ + --domains "${nginx_values[domain]}" +} + +configure_nginx() { + case "${nginx_values[configuration]}" in + "manual") + configure_nginx_local_certs + ;; + "auto") + configure_nginx_letsencrypt + ;; + "none") + configure_nginx_config_file + ;; + "*") + # No action taken when no config is set + # This covers the scenario of no-install-recommends or non-interactive + ;; + esac +} + +info_message() { + local proto + if [ "${nginx_values[configuration]}" == 'none' ]; then + proto='http' + else + proto='https' + fi + + printf -- '\033[32m ===================================================================== \033[0m\n\n' + printf -- '\033[32m Well done! Visit %s://%s to finish installation \033[0m\n\n' "$proto" "${nginx_values[domain]}" + printf -- '\033[32m ===================================================================== \033[0m\n' +} +########################################### +# Script starts here +########################################### + +_echo "entering postinst script: action=$deb_action version=$deb_version" +case "$deb_action" in + + configure) + + get_mysql_values + get_nginx_values + + # mysql setup + if [ "${sql_values[configuration]}" == true ]; then + # Clear debconf cached sensitive responses. + # Stop debconf to avoid stdout clashing with mysql daemon + db_purge + db_stop + configure_mysql + fi + + # nginx setup + configure_nginx + info_message + db_stop + + # Run the migrations process on upgrade + if is_upgrade; then + su -c '/usr/share/php/passbolt/bin/cake passbolt migrate' -s /bin/bash www-data + fi +esac + +#DEBHELPER# diff --git a/debian/postrm b/debian/postrm new file mode 100755 index 0000000000..e01716219d --- /dev/null +++ b/debian/postrm @@ -0,0 +1,96 @@ +#!/bin/bash +# +# postrm +# +# Debian package post removal script +# Covers steps for: upgrading the package, removing, and purging. +# +# Read: https://wiki.debian.org/MaintainerScripts +# +# To display response variables for debugging the installation: +# + +set -e + +. /usr/share/debconf/confmodule + +db_version 2.0 + +# Parameters passed from apt install +deb_action=$1 +deb_version=$2 + +########################################### +# Helper internal functions +########################################### + +_echo() { + [ -z "${VERBOSE}" ] || echo ">>> $1" +} + + +########################################### +# Script starts here +########################################### + +_echo "entering postrm script: action=$deb_action version=$deb_version" + +case "$1" in + + upgrade) + # This stage is invoked when upgrading from x.y to x.z, + # Before postinst configure is invoked. + # Note that during an upgrade, files from the new package + # are not unfolded to their destination paths yet. + ;; + + failed-upgrade) + # This case is called in case the "upgrade" step above would fail. + # Try to recover the problem and go forward with x.z, + # Otherwise apt will jump to abort-upgrade below to rollback to x.y + ;; + + abort-upgrade) + # Do any internal fixup steps before apt rolls back to version x.y + ;; + + remove) + # Called as a result of apt-get remove package + ;; + + purge) + # Called as a result of apt-get remove package; includes configuration files + _echo "postrm: purge" + + # Restore nginx original configuration, remove passbolt site + if [ -d /etc/nginx/sites-available ] && [ -d /etc/nginx/sites-enabled ]; then + _echo "postrm: cleanup passbolt nginx configuration" + ln -sfd /etc/nginx/sites-available/default /etc/nginx/sites-enabled/ + rm -f /etc/nginx/sites-enabled/passbolt + rm -f /etc/nginx/sites-available/passbolt + fi + + # Cleanup folders. + _echo "postrm: cleanup passbolt /var and /etc" + rm -rf /var/lib/passbolt/tmp/cache/* + rm -rf /var/log/passbolt/* + rm -rf /var/lib/passbolt/.gnupg/* + rm -rf /etc/passbolt/* + + # TODO: What needs to happen to mysql passbolt database? + + if [ -f /usr/share/dbconfig-common/dpkg/postrm ]; then + _echo "postrm: prelude manager" + . /usr/share/dbconfig-common/dpkg/postrm + dbc_go prelude-manager "$@" + fi + + _echo "postrm: db_purge" + db_purge + ;; + +esac + +#DEBHELPER# + +db_stop diff --git a/debian/preinst b/debian/preinst new file mode 100755 index 0000000000..5ed7431bd6 --- /dev/null +++ b/debian/preinst @@ -0,0 +1,29 @@ +#!/bin/sh +# +# preinst +# +# Debian package pre installation script +# +# This script takes some important steps based on the installation responses. +# +# To display response variables for debugging the installation: +# + +set -e + +. /usr/share/debconf/confmodule + +########################################### +# Helper internal functions +########################################### + +_echo() { + [ -z "${VERBOSE}" ] || echo ">>> $1" +} + + +########################################### +# Script starts here +########################################### + +_echo "entering preinst script: action=$1" diff --git a/debian/prepare-files b/debian/prepare-files new file mode 100644 index 0000000000..0a8872b7e8 --- /dev/null +++ b/debian/prepare-files @@ -0,0 +1,5 @@ +cron.d.in +docs.in +logrotate.in +triggers.in +lintian-overrides.in diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000000..26c8522334 --- /dev/null +++ b/debian/rules @@ -0,0 +1,68 @@ +#!/usr/bin/make -f +# +# Uncomment line below to get a verbose build +# +#export DH_VERBOSE=1 +#export DH_OPTIONS=-v +# + +# to set the variables on build time + +ifeq ($(PASSBOLT_FLAVOUR), ce) + CONTROL_OP := d +endif + +ifeq ($(PASSBOLT_FLAVOUR), pro) + PASSBOLT_EXTENSIONS := php-ldap, + SED_COMMAND := s + CONTROL_OP := /g +endif + +PASSBOLT_PACKAGE = passbolt-$(PASSBOLT_FLAVOUR)-server +PKG_ROOT := $(CURDIR)/debian/$(PASSBOLT_PACKAGE) +PREPARE_FILES := $(shell cat debian/prepare-files) +PATCHES_FILES := $(shell find debian/postinst debian/patches debian/README.debian.md -type f) + +%: + dh $@ + +check_env: + if [ -z $(PASSBOLT_FLAVOUR) ]; then echo "Please set PASSBOLT_FLAVOUR env var"; exit 1; fi + +override_dh_install: + dh_install + find $(PKG_ROOT)/ -type f -name '.git*' -delete + +override_dh_fixperms: check_env + dh_fixperms + + # Adjust some system directory permissions + chown -R www-data:www-data $(PKG_ROOT)/var/lib/passbolt + chown -R www-data:www-data $(PKG_ROOT)/var/log/passbolt + # Img public folder should be writeable by www-data + chown -R www-data:www-data $(PKG_ROOT)/usr/share/php/passbolt/webroot/img/public + chown -R root:www-data $(PKG_ROOT)/etc/passbolt + # No file should be executable except bin/cake + chmod -R -x+X $(PKG_ROOT)/etc/* + chmod -R -x+X $(PKG_ROOT)/usr/* + chmod -R -x+X $(PKG_ROOT)/var/* + chmod +x $(PKG_ROOT)/usr/share/php/passbolt/bin/cake + chmod +x $(PKG_ROOT)/usr/share/php/passbolt/bin/cake.php + # Configuration files not readable by others + chmod -R o-rw $(PKG_ROOT)/etc/passbolt/* + # www-data needs to write on /etc/passbolt for webinstaller + chmod 0770 $(PKG_ROOT)/etc/passbolt + chmod 0770 $(PKG_ROOT)/etc/passbolt/gpg + chmod -R o-rwx $(PKG_ROOT)/etc/passbolt/* + # Strict permissions for gnupg server keyring + chmod 0700 $(PKG_ROOT)/var/lib/passbolt/.gnupg/ + +debian/control: debian/control.in check_env + # $@ means the target name (debian/control) + # $< is the param passed (debian/control.in) + sed -e "s/@PASSBOLT_FLAVOUR@/$(PASSBOLT_FLAVOUR)/g" -e "$(SED_COMMAND)/@PASSBOLT_EXTENSIONS@/$(PASSBOLT_EXTENSIONS)$(CONTROL_OP)" >$@ <$< + # ${file%.*} stripes the extension from the file name + for file in $(PREPARE_FILES); do cat debian/$$file > debian/passbolt-$(PASSBOLT_FLAVOUR)-server.$${file%.*}; done + for file in $(PATCHES_FILES); do sed -i "s/@PASSBOLT_FLAVOUR@/$(PASSBOLT_FLAVOUR)/g" $$file; done + +.PHONY: debian/control check_env diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000000..163aaf8d82 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/templates b/debian/templates new file mode 100644 index 0000000000..1925ff73ec --- /dev/null +++ b/debian/templates @@ -0,0 +1,138 @@ +Template: passbolt/mysql-configuration +Type: boolean +Choices: true, false +Default: false +Description: Create a passbolt database on the local mysql? + . + This script will guide you to create an empty database + . + and grant permissions to a user for passbolt to use. + +Template: passbolt/mysql-username +Type: string +Default: root +Description: MySQL administator username: + Please, provide a username with enough privileges + . + to create databases on your mysql server. + +Template: passbolt/mysql-password +Type: password +Description: MySQL administator password: + Please, provide a password for the mysql admin user. + +Template: passbolt/mysql-passbolt-username +Type: string +Default: passboltadmin +Description: Passbolt database user: + Choose a new username that Passbolt will use to connect to mysql + +Template: passbolt/mysql-passbolt-password +Type: password +Description: Passbolt database password: + Choose a new password for the Passbolt mysql user + +Template: passbolt/mysql-passbolt-password-repeat +Type: password +Description: Repeat the password to confirm: + Passwords must match + +Template: passbolt/non-empty-password +Type: error +Description: Empty passwords are not accepted + Please choose a new non-empty password. + +Template: passbolt/db_invalid_characters +Type: error +Description: Invalid database name + Database name can not be empty and can not contain dashes '-' or whitespaces, please try again. + +Template: passbolt/non-matching-passwords +Type: error +Description: The provided passwords do not match + Passwords must match, please try again. + +Template: passbolt/mysql-passbolt-dbname +Type: string +Default: passboltdb +Description: Passbolt database name: + Please, provide the database name that passbolt will use. + +Template: passbolt/nginx-configuration +Type: boolean +Choices: true, false +Default: false +Description: Do you want to configure the nginx server? + . + Passbolt requires nginx or apache to serve http requests + . + This script can automatically configure nginx for you. + +Template: passbolt/nginx-configuration-three-choices +Type: select +Choices: none, manual, auto +Default: none +Description: Passbolt nginx setup: + This script adds a nginx site for passbolt. Select which SSL setup for the nginx config: + . + "none" will delay SSL configuration to a later stage. + . + "manual" allows you to provide the SSL keys. + . + "auto" will generate SSL keys for your domain through Letsencrypt.org + +Template: passbolt/nginx-configuration-two-choices +Type: select +Choices: none, manual +Default: none +Description: Passbolt nginx setup: + This script adds a nginx site for passbolt. Select which SSL setup for the nginx config: + . + "none" will delay configuration to a later stage. + . + "manual" allows you to provide your SSL keys. + +Template: passbolt/nginx-domain +Type: string +Description: Passbolt domain name: + Provide the domain name where you will run Passbolt. + . + If you do not have a domain name or you are not sure, introduce the ip address of this machine. + +Template: passbolt/nginx-domain-incorrect +Type: error +Description: Domain validation + The domain name format is incorrect, it should be in the form example.com. + . + Please try again. + +Template: passbolt/nginx-letsencrypt-email +Type: string +Default: admin@mydomain.com +Description: Letsencrypt email: + Provide an administrative email address for your domain. + . + The email address is required by letsencrypt to send you notifications + . + about expiration of your certificates. + +Template: passbolt/nginx-certificate-file +Type: string +Description: Provide the filename for the SSL fullchain key: + This is the path where you have your SSL certificate stored. + If you have not uploaded your SSL certificate to this machine, do it now. + +Template: passbolt/nginx-certificate-key-file +Type: string +Description: Provide the filename for the SSL Private Key: + If you have not uploaded your SSL key to this machine, do it now. + +Template: passbolt/certificate-file-not-found +Type: error +Description: The SSL certificate file could not be found, please try again. + Please provide the correct absolute path where your certificate is stored. + +Template: passbolt/certificate-key-file-not-found +Type: error +Description: The SSL key file could not be found, please try again + Please provide the correct absolute path where your key is stored. diff --git a/debian/triggers.in b/debian/triggers.in new file mode 100644 index 0000000000..7db4459cd8 --- /dev/null +++ b/debian/triggers.in @@ -0,0 +1,5 @@ +activate-noawait nginx-reload +# This restarts php-fpm +# php-gnupg does not trigger php-fpm restarts so we do it in order to have a working installation +# TODO version of php should be loaded dynamically +activate-noawait /etc/php/7.3/fpm/conf.d diff --git a/kitchen.yml b/kitchen.yml new file mode 100644 index 0000000000..fd6e66ea1b --- /dev/null +++ b/kitchen.yml @@ -0,0 +1,53 @@ +--- +driver: + name: dokken + volumes: + - <%= ENV['PWD'] %>:/tmp/passbolt + +transport: + name: dokken + +provisioner: + name: dokken + chef_license: accept-no-persist + attributes: + dest_dir: '/tmp/passbolt' + passbolt_flavour: <%= ENV['PASSBOLT_FLAVOUR'] %> + +verifier: + name: inspec + inputs: + passbolt_flavour: <%= ENV['PASSBOLT_FLAVOUR'] %> + +platforms: + - name: debian-buster + driver: + image: debian:buster + ports: + - '127.0.0.1:8080:8080' + - name: ubuntu-18.04 + - name: ubuntu-19.10 + +suites: + - name: filesystem-benchmarks + run_list: + - recipe[passbolt_package::passbolt_package_build] + - recipe[passbolt_package::passbolt_install] + attributes: + parameters: '--no-install-recommends' + - name: purge-benchmarks + run_list: + - recipe[passbolt_package::passbolt_package_build] + - recipe[passbolt_package::passbolt_install_and_purge] + attributes: + parameters: '--no-install-recommends' + - name: runtime-benchmarks + run_list: + - recipe[passbolt_package::passbolt_package_build] + - recipe[passbolt_package::passbolt_install_mariadb_nginx] + attributes: + - name: break-benchmarks + run_list: + - recipe[passbolt_package::passbolt_package_build] + - recipe[passbolt_package::passbolt_install_break_and_recover] + attributes: diff --git a/tests/cookbooks/passbolt_package/.delivery/project.toml b/tests/cookbooks/passbolt_package/.delivery/project.toml new file mode 100644 index 0000000000..c23d1fe7ce --- /dev/null +++ b/tests/cookbooks/passbolt_package/.delivery/project.toml @@ -0,0 +1,32 @@ +# Delivery for Local Phases Execution +# +# This file allows you to execute test phases locally on a workstation or +# in a CI pipeline. The delivery-cli will read this file and execute the +# command(s) that are configured for each phase. You can customize them +# by just modifying the phase key on this file. +# +# By default these phases are configured for Cookbook Workflow only +# + +[local_phases] +unit = "chef exec rspec spec/" +lint = "chef exec cookstyle" +# foodcritic has been deprecated in favor of cookstyle so we skip the syntax +# phase now. +syntax = "echo skipping syntax phase. Use lint phase instead." +provision = "chef exec kitchen create" +deploy = "chef exec kitchen converge" +smoke = "chef exec kitchen verify" +# The functional phase is optional, you can define it by uncommenting +# the line below and running the command: `delivery local functional` +# functional = "" +cleanup = "chef exec kitchen destroy" + +# Remote project.toml file +# +# Instead of the local phases above, you may specify a remote URI location for +# the `project.toml` file. This is useful for teams that wish to centrally +# manage the behavior of the `delivery local` command across many different +# projects. +# +# remote_file = "https://url/project.toml" diff --git a/tests/cookbooks/passbolt_package/.gitignore b/tests/cookbooks/passbolt_package/.gitignore new file mode 100644 index 0000000000..9abf29fa8e --- /dev/null +++ b/tests/cookbooks/passbolt_package/.gitignore @@ -0,0 +1,22 @@ +.vagrant +*~ +*# +.#* +\#*# +.*.sw[a-z] +*.un~ + +# Bundler +Gemfile.lock +gems.locked +bin/* +.bundle/* + +# test kitchen +.kitchen/ +kitchen.local.yml + +# Chef +Berksfile.lock +.zero-knife.rb +Policyfile.lock.json diff --git a/tests/cookbooks/passbolt_package/metadata.rb b/tests/cookbooks/passbolt_package/metadata.rb new file mode 100644 index 0000000000..39e6d4c167 --- /dev/null +++ b/tests/cookbooks/passbolt_package/metadata.rb @@ -0,0 +1,7 @@ +name 'passbolt_package' +maintainer 'Passbolt SA' +maintainer_email 'contact@passbolt.com' +license 'All Rights Reserved' +description 'Installs/Configures passbolt in a variety of environments' +version '0.1.0' +chef_version '>= 14.0' diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_install.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_install.rb new file mode 100644 index 0000000000..03740e300c --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_install.rb @@ -0,0 +1,16 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_install +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# + +apt_update + +# TODO: Change this command when the repo is available + +execute "Install passbolt" do + command "DEBIAN_FRONTEND=noninteractive apt-get install -y #{node['parameters']} /tmp/passbolt/passbolt*.deb \ + && service php$(php -r 'echo PHP_VERSION;' | sed 's:\\(7\\.[0-3]\\).*:\\1:')-fpm start #{node.has_key?(:parameters) ? '' : '&& service nginx start'}" + action :run +end diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_install_and_purge.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_install_and_purge.rb new file mode 100644 index 0000000000..12c0c158b3 --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_install_and_purge.rb @@ -0,0 +1,14 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_install_and_purge +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# + +apt_update + +include_recipe '::passbolt_install' + +package "passbolt-#{node['passbolt_flavour']}-server" do + action :purge +end diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_install_break_and_recover.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_install_break_and_recover.rb new file mode 100644 index 0000000000..33eab92667 --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_install_break_and_recover.rb @@ -0,0 +1,28 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_install_break_and_recover.rb +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# +apt_update + +package 'Install mariadb and nginx' do + package_name ['debconf-utils', 'curl', 'nginx', 'default-mysql-server'] + action :install +end + +execute "Break nginx and mysql" do + command "mv /usr/sbin/nginx /root && mv /usr/bin/mysql /root" + action :run +end + +include_recipe '::passbolt_responses_nginx_mysql' +include_recipe '::passbolt_install_breaks' + +execute "Recover nginx and mysql" do + command "mv /root/nginx /usr/sbin && mv /root/mysql /usr/bin" + action :run +end + +include_recipe '::passbolt_responses_nginx_mysql' +include_recipe '::passbolt_install' diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_install_breaks.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_install_breaks.rb new file mode 100644 index 0000000000..ba104958bf --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_install_breaks.rb @@ -0,0 +1,15 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_install_breaks +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# + +apt_update + +execute "Install passbolt, expect to break, display output" do + command "VERBOSE=1 DEBIAN_FRONTEND=noninteractive apt-get install -y #{node['parameters']} /tmp/passbolt/passbolt*.deb" + ignore_failure true + live_stream true + action :run +end diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_install_mariadb_nginx.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_install_mariadb_nginx.rb new file mode 100644 index 0000000000..d0d5862d83 --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_install_mariadb_nginx.rb @@ -0,0 +1,20 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_install_mariadb_nginx +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# +apt_update + +package 'mariadb-server' do + package_name [ 'debconf-utils', 'curl', 'mariadb-server', 'nginx' ] + action :install +end + +execute "Start mysql" do + command "service mysql start" + action :run +end + +include_recipe '::passbolt_responses_nginx_mysql' +include_recipe '::passbolt_install' diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_package_build.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_package_build.rb new file mode 100644 index 0000000000..ffc30b1874 --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_package_build.rb @@ -0,0 +1,46 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_package_build +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# + +if (Dir.glob("#{node['dest_dir']}/passbolt-*.deb").empty? or + Dir.glob("#{node['dest_dir']}/vendor/*").empty?) then + apt_update 'all platforms' do + action :update + end +end + +if Dir.glob("#{node['dest_dir']}/vendor/*").empty? then + package 'Install composer' do + package_name 'composer' + action :install + end + + execute 'Download vendors' do + cwd "#{node['dest_dir']}" + command 'composer install -o --prefer-dist --no-dev --ignore-platform-reqs --no-interaction' + action :run + end +end + +if Dir.glob("#{node['dest_dir']}/passbolt-*.deb").empty? then + package 'Install dev dependencies' do + package_name ['devscripts', 'build-essential', 'apt-utils', 'fakeroot', 'equivs', 'cdbs'] + action :install + end + + execute 'Build debian package' do + cwd "#{node['dest_dir']}" + command "export PASSBOLT_FLAVOUR=#{node['passbolt_flavour']} \ + && make -f debian/rules debian/control \ + && mk-build-deps -irt'apt-get --no-install-recommends -yV' debian/control && dpkg-checkbuilddeps \ + && debuild --preserve-envvar PASSBOLT_FLAVOUR -us -uc -b -i -I \ + && cp ../*.deb . \ + && cp ../*.build . \ + && cp ../*.buildinfo . \ + && cp ../*.changes ." + action :run + end +end diff --git a/tests/cookbooks/passbolt_package/recipes/passbolt_responses_nginx_mysql.rb b/tests/cookbooks/passbolt_package/recipes/passbolt_responses_nginx_mysql.rb new file mode 100644 index 0000000000..55b179c95b --- /dev/null +++ b/tests/cookbooks/passbolt_package/recipes/passbolt_responses_nginx_mysql.rb @@ -0,0 +1,26 @@ +# +# Cookbook:: docker_test +# Recipe:: passbolt_responses_nginx_mysql.rb +# +# Copyright:: 2020, The Authors, All Rights Reserved. +# + +# Default values: +# mysql-config: false +# db admin: root +# db admin-pass: empty +# db user: passboltadmin +# db pass: empty +# db name: passboltdb +# nginx-config: false +# nginx-ssl: none +# nginx-domain: empty (postinst sets _) + +execute "Provide responses to customize nginx and mysql" do + command "printf 'passbolt-#{node['passbolt_flavour']}-server passbolt/mysql-configuration select true' | debconf-set-selections ; \ + printf 'passbolt-#{node['passbolt_flavour']}-server passbolt/mysql-passbolt-password password hawhawhaw' | debconf-set-selections ; \ + printf 'passbolt-#{node['passbolt_flavour']}-server passbolt/nginx-configuration select true' | debconf-set-selections ; \ + printf 'passbolt-#{node['passbolt_flavour']}-server passbolt/nginx-configuration-two-choices select none' | debconf-set-selections ; \ + printf 'passbolt-#{node['passbolt_flavour']}-server passbolt/nginx-domain string 127.0.0.1' | debconf-set-selections" + action :run +end diff --git a/tests/integration/break-benchmarks/controls/break.rb b/tests/integration/break-benchmarks/controls/break.rb new file mode 100644 index 0000000000..e11dbe69b0 --- /dev/null +++ b/tests/integration/break-benchmarks/controls/break.rb @@ -0,0 +1,11 @@ +title 'Passbolt package break and recover healthcheck' + +control 'passbolt-break-01' do + impact 0.9 + title 'Check passbolt package recovery' + desc 'Check that passbolt package has been recovered and installed' + + describe package("passbolt-#{input('passbolt_flavour')}-server") do + it { should be_installed } + end +end diff --git a/tests/integration/break-benchmarks/inspec.yml b/tests/integration/break-benchmarks/inspec.yml new file mode 100644 index 0000000000..43f0c02696 --- /dev/null +++ b/tests/integration/break-benchmarks/inspec.yml @@ -0,0 +1,8 @@ +name: break-benchmarks +title: Passbolt break and recover benchmarks +maintainer: Passbolt SA +copyright: Passbolt SA +copyright_email: support@passbolt.com +license: Apache-2.0 +summary: An InSpec Compliance Profile +version: 0.1.0 diff --git a/tests/integration/filesystem-benchmarks/README.md b/tests/integration/filesystem-benchmarks/README.md new file mode 100644 index 0000000000..2aee95cbf6 --- /dev/null +++ b/tests/integration/filesystem-benchmarks/README.md @@ -0,0 +1,3 @@ +# Example InSpec Profile + +This example shows the implementation of an InSpec profile. diff --git a/tests/integration/filesystem-benchmarks/controls/configuration.rb b/tests/integration/filesystem-benchmarks/controls/configuration.rb new file mode 100644 index 0000000000..3da727808c --- /dev/null +++ b/tests/integration/filesystem-benchmarks/controls/configuration.rb @@ -0,0 +1,143 @@ +# encoding: utf-8 +# copyright: 2018, The Authors + +title 'Passbolt filesystem configuration benchmarks' + +config_dir = '/etc/passbolt' +gnupg_dir = '/var/lib/passbolt/.gnupg' + +# you add controls here +control 'passbolt-config-01' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'app.php is installed' # A human-readable title + desc 'app.php config file is installed and with correct permissions' + describe file("#{config_dir}/app.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-02' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'bootstrap.php file is installed' # A human-readable title + desc 'bootstrap.php file is present with correct permissions' + describe file("#{config_dir}/bootstrap.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-03' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'bootstrap_cli.php file is installed' # A human-readable title + desc 'bootstrap_cli.php file is present with correct permissions' + describe file("#{config_dir}/bootstrap_cli.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-04' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'bootstrap_plugins.php file is installed' # A human-readable title + desc 'bootstrap_plugins.php file is present with correct permissions' + describe file("#{config_dir}/bootstrap_plugins.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-05' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'file_storage.php file is installed' # A human-readable title + desc 'file_storage.php file is present with correct permissions' + describe file("#{config_dir}/file_storage.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-06' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'requirements.php file is installed' # A human-readable title + desc 'requirements.php file is present with correct permissions' + describe file("#{config_dir}/requirements.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-07' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'routes.php file is installed' # A human-readable title + desc 'routes.php file is present with correct permissions' + describe file("#{config_dir}/routes.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-08' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'version.php file is installed' # A human-readable title + desc 'version.php file is present with correct permissions' + describe file("#{config_dir}/version.php") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00640' } + end +end + +# you add controls here +control 'passbolt-config-09-1' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'gpg directory is installed' # A human-readable title + desc 'gpg directory is present with correct permissions' + describe directory("#{config_dir}/gpg") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00770' } + it 'should be empty' do + expect(command("ls #{config_dir}/gpg | wc -l").stdout).to eq "0\n" + end + end +end + +# you add controls here +control 'passbolt-config-09-2' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'gnugpg directory is installed' # A human-readable title + desc 'gnugpg directory is present with correct permissions for web server user' + describe directory("#{gnupg_dir}") do # The actual test + it { should exist } + its('owner') { should eq 'www-data' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00700' } + it 'should be empty' do + expect(command("ls #{gnupg_dir} | wc -l").stdout).to eq "0\n" + end + end +end diff --git a/tests/integration/filesystem-benchmarks/controls/source.rb b/tests/integration/filesystem-benchmarks/controls/source.rb new file mode 100644 index 0000000000..c1e6291dca --- /dev/null +++ b/tests/integration/filesystem-benchmarks/controls/source.rb @@ -0,0 +1,68 @@ +title 'Passbolt source files benchmark' + +source_dir = '/usr/share/php/passbolt/src' +bin_dir = '/usr/share/php/passbolt/bin' + +control 'passbolt-src-01' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'source directory' # A human-readable title + desc 'source directory is present and have the correct permissions' + describe directory("#{source_dir}") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00755' } + end +end + +control 'passbolt-src-02' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'source files' # A human-readable title + desc 'source files are present and have the correct permissions' + command("find #{source_dir} -type f").stdout.split.each do |item| + describe file(item) do + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00644' } + end + end +end + +control 'passbolt-src-03' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'source directories' # A human-readable title + desc 'source directories are present and have the correct permissions' + command("find #{source_dir} -type d").stdout.split.each do |item| + describe file(item) do + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00755' } + end + end +end + +control 'passbolt-src-04' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'bin test and ci-test files' # A human-readable title + desc 'Executable files for testing' + files = [ 'test', 'ci-test' ] + files.each do |item| + describe file("#{bin_dir}/#{item}") do + it { should_not exist } + end + end +end + +control 'passbolt-src-05' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'cake bin scripts' # A human-readable title + desc 'Cake Executable files' + files = [ 'cake', 'cake.php' ] + files.each do |item| + describe file("#{bin_dir}/#{item}") do + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00755' } + end + end +end diff --git a/tests/integration/filesystem-benchmarks/controls/systemfiles.rb b/tests/integration/filesystem-benchmarks/controls/systemfiles.rb new file mode 100644 index 0000000000..35a4b935d6 --- /dev/null +++ b/tests/integration/filesystem-benchmarks/controls/systemfiles.rb @@ -0,0 +1,93 @@ +title 'Passbolt system files benchmark' + +logs_dir = '/var/log/passbolt' +tmp_dir = '/var/lib/passbolt/tmp' +config_dir = '/etc/passbolt' +examples_dir = '/usr/share/passbolt/examples' +docs_dir = "/usr/share/doc/passbolt-#{input('passbolt_flavour')}-server" +crontabs_dir = '/etc/cron.d' +logrotate_dir = '/etc/logrotate.d' + +control 'passbolt-logs-01' do + impact 1 + title 'passbolt logs directory' + desc 'passbolt logs directory is present and has write permissions for www user' + describe directory("#{logs_dir}") do + it { should exist } + its('owner') { should eq 'www-data' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '0755' } + end +end + +control 'passbolt-tmp-01' do + impact 1 + title 'passbolt temporary directory' + desc 'passbolt temporary directory is present and has write permissions for www user' + describe directory("#{tmp_dir}") do + it { should exist } + its('owner') { should eq 'www-data' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '0755' } + end +end + +control 'passbolt-config-01' do + impact 1 + title 'passbolt config directory' + desc 'passbolt config directory is present and has write permissions for www user' + describe directory("#{config_dir}") do + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'www-data' } + its('mode') { should cmp '00770' } + end +end + +control 'passbolt-examples-01' do + impact 1 + title 'passbolt configuration examples directory' + desc 'passbolt config examples directory is present' + describe directory("#{examples_dir}") do + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00755' } + end +end + +control 'passbolt-docs-01' do + impact 1 + title 'passbolt docs directory' + desc 'passbolt docs directory is present' + describe directory("#{docs_dir}") do + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00755' } + end +end + +control 'passbolt-crontab' do + impact 0.5 + title 'passbolt crontab job' + desc 'the passbolt crontab job must be installed' + describe file("#{crontabs_dir}/passbolt-#{input('passbolt_flavour')}-server") do + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00644' } + end +end + +control 'passbolt-logrotate' do + impact 0.5 + title 'passbolt logrotate' + desc 'the passbolt crontab job must be installed' + describe file("#{logrotate_dir}/passbolt-#{input('passbolt_flavour')}-server") do + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00644' } + end +end diff --git a/tests/integration/filesystem-benchmarks/controls/webroot.rb b/tests/integration/filesystem-benchmarks/controls/webroot.rb new file mode 100644 index 0000000000..02871c23fe --- /dev/null +++ b/tests/integration/filesystem-benchmarks/controls/webroot.rb @@ -0,0 +1,53 @@ +title 'Passbolt webroot files benchmark' + +source_dir = '/usr/share/php/passbolt/webroot' + +control 'passbolt-webroot-01' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'webroot directory' # A human-readable title + desc 'webroot directory is present and have the correct permissions' + describe directory("#{source_dir}") do # The actual test + it { should exist } + its('owner') { should eq 'root' } + its('group') { should eq 'root' } + its('mode') { should cmp '00755' } + end +end + +control 'passbolt-webroot-02' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'webroot dirs' # A human-readable title + desc 'webroot files are present and have the correct permissions' + command("find #{source_dir} -type d").stdout.split.each do |item| + describe file(item) do + owner = 'root' + group = 'root' + if item.include? "public" + owner = 'www-data' + group = 'www-data' + end + its('owner') { should eq owner } + its('group') { should eq group } + its('mode') { should cmp '00755' } + end + end +end + +control 'passbolt-webroot-03' do # A unique ID for this control + impact 1 # The criticality, if this control fails. + title 'webroot files' # A human-readable title + desc 'webroot files are present and have the correct permissions' + command("find #{source_dir} -type f").stdout.split.each do |item| + describe file(item) do + owner = 'root' + group = 'root' + if item.include? "public" + owner = 'www-data' + group = 'www-data' + end + its('owner') { should eq owner } + its('group') { should eq group } + its('mode') { should cmp '00644' } + end + end +end diff --git a/tests/integration/filesystem-benchmarks/inspec.yml b/tests/integration/filesystem-benchmarks/inspec.yml new file mode 100644 index 0000000000..a12e097863 --- /dev/null +++ b/tests/integration/filesystem-benchmarks/inspec.yml @@ -0,0 +1,8 @@ +name: filesystem-benchmarks +title: Passbolt Filesystem benchmarks +maintainer: Diego Lendoiro +copyright: Passbolt SA +copyright_email: diego@passbolt.com +license: Apache-2.0 +summary: An InSpec Compliance Profile +version: 0.1.0 diff --git a/tests/integration/filesystem-benchmarks/libraries/.gitkeep b/tests/integration/filesystem-benchmarks/libraries/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/integration/purge-benchmarks/controls/cache.rb b/tests/integration/purge-benchmarks/controls/cache.rb new file mode 100644 index 0000000000..c8d3ddcc41 --- /dev/null +++ b/tests/integration/purge-benchmarks/controls/cache.rb @@ -0,0 +1,10 @@ +title 'Check passbolt has cleared debconf cache' + +control 'passbolt-cache-0' do + impact 0.5 + title 'debconf cache data' + desc 'debconf cached parameters for passbolt should not exist' + describe command("debconf-get-selections | grep passbolt") do + its('stdout') { should eq '' } + end +end diff --git a/tests/integration/purge-benchmarks/controls/purge.rb b/tests/integration/purge-benchmarks/controls/purge.rb new file mode 100644 index 0000000000..55cba54e4d --- /dev/null +++ b/tests/integration/purge-benchmarks/controls/purge.rb @@ -0,0 +1,29 @@ +title 'Passbolt package purge healthcheck' + +control 'passbolt-purge-01' do + impact 0.9 + title 'Check that passbolt package is NOT installed' + desc 'Check that passbolt package has been correctly purged' + + describe package("passbolt-#{input('passbolt_flavour')}-server") do + it { should_not be_installed } + end +end + +control 'passbolt-purge-02' do + impact 0.1 + title 'conf files erased' + desc 'Configuration files are deleted on purge' + describe directory('/etc/passbolt') do + it { should_not exist } + end +end + +control 'passbolt-purge-03' do + impact 0.2 + title 'php files are erased' + desc 'Passbolt files are removed' + describe directory('/usr/share/php/passbolt') do + it { should_not exist } + end +end diff --git a/tests/integration/purge-benchmarks/inspec.yml b/tests/integration/purge-benchmarks/inspec.yml new file mode 100644 index 0000000000..916fa74f59 --- /dev/null +++ b/tests/integration/purge-benchmarks/inspec.yml @@ -0,0 +1,8 @@ +name: runtime-benchmarks +title: Passbolt runtime benchmarks +maintainer: Passbolt SA +copyright: Passbolt SA +copyright_email: support@passbolt.com +license: Apache-2.0 +summary: An InSpec Compliance Profile +version: 0.1.0 diff --git a/tests/integration/runtime-benchmarks/controls/cache.rb b/tests/integration/runtime-benchmarks/controls/cache.rb new file mode 100644 index 0000000000..c8d3ddcc41 --- /dev/null +++ b/tests/integration/runtime-benchmarks/controls/cache.rb @@ -0,0 +1,10 @@ +title 'Check passbolt has cleared debconf cache' + +control 'passbolt-cache-0' do + impact 0.5 + title 'debconf cache data' + desc 'debconf cached parameters for passbolt should not exist' + describe command("debconf-get-selections | grep passbolt") do + its('stdout') { should eq '' } + end +end diff --git a/tests/integration/runtime-benchmarks/controls/healthcheck.rb b/tests/integration/runtime-benchmarks/controls/healthcheck.rb new file mode 100644 index 0000000000..1d730b6fc3 --- /dev/null +++ b/tests/integration/runtime-benchmarks/controls/healthcheck.rb @@ -0,0 +1,21 @@ +title 'Passbolt runtime healthcheck' + +control 'passbolt-runtime-01' do + impact 0.9 + title 'Check if passbolt responds to the install url' + desc 'Check that passbolt is running and waiting to be configured' + describe http('http://127.0.0.1/install') do + its('status') { should eq 200 } + its('body') { should include 'Passbolt is not configured yet!' } + end +end + +control 'passbolt-runtime-02' do + impact 1 + title 'Check if passbolt replies' + desc 'Check if passbolt app is responding' + describe http('http://127.0.0.1/install/system_check') do + its('status') { should eq 200 } + its('body') { should include 'Open source password manager for teams' } + end +end diff --git a/tests/integration/runtime-benchmarks/controls/mysql.rb b/tests/integration/runtime-benchmarks/controls/mysql.rb new file mode 100644 index 0000000000..f5c5115b9e --- /dev/null +++ b/tests/integration/runtime-benchmarks/controls/mysql.rb @@ -0,0 +1,13 @@ +title 'Check passbolt database' + +sql=mysql_session('root','') + +control 'passbolt-mysql-0' do + impact 1 + title 'Check that passbolt database is present' + desc 'Passbolt installation has created its database' + + describe sql.query('show databases;') do + its('stdout') { should include('passboltdb') } + end +end diff --git a/tests/integration/runtime-benchmarks/inspec.yml b/tests/integration/runtime-benchmarks/inspec.yml new file mode 100644 index 0000000000..ca7385b0a8 --- /dev/null +++ b/tests/integration/runtime-benchmarks/inspec.yml @@ -0,0 +1,8 @@ +name: runtime-benchmarks +title: Passbolt runtime benchmarks +maintainer: Passbolt SA +copyright: Albert Casals +copyright_email: skarbat@gmail.com +license: Apache-2.0 +summary: An InSpec Compliance Profile +version: 0.1.0 From de22108eb1930548181324a4eaaffbc4c6172096 Mon Sep 17 00:00:00 2001 From: Diego Lendoiro Date: Thu, 4 Jun 2020 12:18:06 +0200 Subject: [PATCH 004/287] Changed: debian changelog updated [publish-package] --- debian/changelog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index d40595c858..ef48ee495e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -passbolt-pro-server (2.12.0-1) stretch; urgency=medium +passbolt-ce-server (2.12.1-1+beta) stretch; urgency=medium * Refactor config script * Refactor postinst script * Added questions for nginx setup @@ -11,13 +11,13 @@ passbolt-pro-server (2.12.0-1) stretch; urgency=medium -- Diego Lendoiro Thu, 21 May 2020 18:24:00 +0000 -passbolt-pro-server (2.12.0-0) stretch; urgency=medium +passbolt-ce-server (2.12.0-0) stretch; urgency=medium * Created an automated debian package -- Albert Casals Fri, 27 Dec 2019 01:15:00 +0100 -passbolt-pro-server (2.7.1-0) stretch; urgency=medium +passbolt-ce-server (2.7.1-0) stretch; urgency=medium * Initial release. From 1fa52db0c08d5d154a4f5f791dbccdc5d1af97fc Mon Sep 17 00:00:00 2001 From: Diego Lendoiro Date: Thu, 4 Jun 2020 13:36:58 +0200 Subject: [PATCH 005/287] Changed: updated bundles --- Gemfile.lock | 229 +++++++++++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 117 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 690710f004..c84eca8c18 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,173 +1,173 @@ GEM remote: https://rubygems.org/ specs: - activesupport (5.2.4.2) + activesupport (5.2.4.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - addressable (2.5.2) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) aws-eventstream (1.1.0) - aws-partitions (1.302.0) - aws-sdk-apigateway (1.38.0) + aws-partitions (1.324.0) + aws-sdk-apigateway (1.41.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-apigatewayv2 (1.19.0) + aws-sdk-apigatewayv2 (1.21.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-athena (1.24.0) + aws-sdk-athena (1.27.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) aws-sdk-autoscaling (1.22.0) aws-sdk-core (~> 3, >= 3.52.1) aws-sigv4 (~> 1.1) - aws-sdk-budgets (1.28.0) + aws-sdk-budgets (1.30.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudformation (1.33.0) + aws-sdk-cloudformation (1.36.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudhsm (1.20.0) + aws-sdk-cloudhsm (1.22.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudhsmv2 (1.21.0) + aws-sdk-cloudhsmv2 (1.23.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudtrail (1.21.0) + aws-sdk-cloudtrail (1.23.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatch (1.36.0) + aws-sdk-cloudwatch (1.38.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-cloudwatchlogs (1.29.0) + aws-sdk-cloudwatchlogs (1.31.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-codecommit (1.31.0) + aws-sdk-codecommit (1.33.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-codedeploy (1.28.0) + aws-sdk-codedeploy (1.31.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-codepipeline (1.29.0) + aws-sdk-codepipeline (1.31.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-configservice (1.43.0) + aws-sdk-configservice (1.45.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-core (3.94.0) + aws-sdk-core (3.97.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) aws-sigv4 (~> 1.1) jmespath (~> 1.0) - aws-sdk-costandusagereportservice (1.19.0) + aws-sdk-costandusagereportservice (1.21.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-dynamodb (1.45.0) + aws-sdk-dynamodb (1.48.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-ec2 (1.154.0) + aws-sdk-ec2 (1.164.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-ecr (1.26.0) + aws-sdk-ecr (1.30.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-ecs (1.60.0) + aws-sdk-ecs (1.63.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-efs (1.26.0) + aws-sdk-efs (1.29.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-eks (1.35.0) + aws-sdk-eks (1.37.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticache (1.31.0) + aws-sdk-elasticache (1.36.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticbeanstalk (1.28.0) + aws-sdk-elasticbeanstalk (1.30.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticloadbalancing (1.20.0) + aws-sdk-elasticloadbalancing (1.22.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticloadbalancingv2 (1.41.0) + aws-sdk-elasticloadbalancingv2 (1.44.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-elasticsearchservice (1.33.0) + aws-sdk-elasticsearchservice (1.36.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-firehose (1.26.0) + aws-sdk-firehose (1.28.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-iam (1.36.0) + aws-sdk-iam (1.39.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-kafka (1.19.0) + aws-sdk-kafka (1.21.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-kinesis (1.21.0) + aws-sdk-kinesis (1.23.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-kms (1.30.0) + aws-sdk-kms (1.33.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-lambda (1.39.0) + aws-sdk-lambda (1.42.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) aws-sdk-organizations (1.17.0) aws-sdk-core (~> 3, >= 3.39.0) aws-sigv4 (~> 1.0) - aws-sdk-rds (1.83.0) + aws-sdk-rds (1.85.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-redshift (1.41.0) + aws-sdk-redshift (1.43.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-route53 (1.32.0) + aws-sdk-route53 (1.35.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-route53domains (1.20.0) + aws-sdk-route53domains (1.22.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-route53resolver (1.12.0) + aws-sdk-route53resolver (1.14.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.63.0) - aws-sdk-core (~> 3, >= 3.83.0) + aws-sdk-s3 (1.67.1) + aws-sdk-core (~> 3, >= 3.96.1) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) - aws-sdk-securityhub (1.23.0) + aws-sdk-securityhub (1.26.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-ses (1.28.0) + aws-sdk-ses (1.30.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-sms (1.18.0) + aws-sdk-sms (1.20.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-sns (1.22.0) + aws-sdk-sns (1.24.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-sqs (1.24.0) + aws-sdk-sqs (1.26.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sdk-ssm (1.73.0) + aws-sdk-ssm (1.79.0) aws-sdk-core (~> 3, >= 3.71.0) aws-sigv4 (~> 1.1) - aws-sigv4 (1.1.2) + aws-sigv4 (1.1.4) aws-eventstream (~> 1.0, >= 1.0.2) - azure_graph_rbac (0.17.1) - ms_rest_azure (~> 0.11.0) - azure_mgmt_key_vault (0.17.5) - ms_rest_azure (~> 0.11.1) - azure_mgmt_resources (0.17.8) - ms_rest_azure (~> 0.11.1) - azure_mgmt_security (0.18.0) - ms_rest_azure (~> 0.11.1) - azure_mgmt_storage (0.20.1) - ms_rest_azure (~> 0.11.1) - bcrypt_pbkdf (1.0.1) - berkshelf (7.0.9) + azure_graph_rbac (0.17.2) + ms_rest_azure (~> 0.12.0) + azure_mgmt_key_vault (0.17.6) + ms_rest_azure (~> 0.12.0) + azure_mgmt_resources (0.17.9) + ms_rest_azure (~> 0.12.0) + azure_mgmt_security (0.18.1) + ms_rest_azure (~> 0.12.0) + azure_mgmt_storage (0.21.1) + ms_rest_azure (~> 0.12.0) + bcrypt_pbkdf (1.1.0.rc1) + berkshelf (7.0.10) chef (>= 13.6.52) chef-config cleanroom (~> 1.0) @@ -182,12 +182,13 @@ GEM thor (>= 0.20) bigdecimal (2.0.0) builder (3.2.4) - chef (15.10.12) + chef (16.1.16) addressable - bcrypt_pbkdf (~> 1.0) + bcrypt_pbkdf (= 1.1.0.rc1) bundler (>= 1.10) - chef-config (= 15.10.12) - chef-utils (= 15.10.12) + chef-config (= 16.1.16) + chef-utils (= 16.1.16) + chef-vault chef-zero (>= 14.0.11) diff-lcs (~> 1.2, >= 1.2.4) ed25519 (~> 1.2) @@ -195,7 +196,7 @@ GEM ffi (~> 1.9, >= 1.9.25) ffi-libarchive ffi-yajl (~> 2.2) - highline (>= 1.6.9, < 2) + highline (>= 1.6.9, < 3) iniparse (~> 1.4) license-acceptance (~> 1.0, >= 1.0.5) mixlib-archive (>= 0.4, < 2.0) @@ -206,7 +207,8 @@ GEM net-sftp (~> 2.1, >= 2.1.2) net-ssh (>= 4.2, < 6) net-ssh-multi (~> 1.2, >= 1.2.1) - ohai (~> 15.0) + ohai (~> 16.0) + pastel plist (~> 3.2) proxifier (~> 1.0) syslog-logger (~> 1.6) @@ -214,9 +216,9 @@ GEM train-winrm (>= 0.2.5) tty-screen (~> 0.6) uuidtools (~> 2.1.5) - chef-cli (2.0.0) - addressable (>= 2.3.5, < 2.6) - chef (>= 14.0) + chef-cli (3.0.1) + addressable (>= 2.3.5, < 2.8) + chef (>= 15.0) cookbook-omnifetch (~> 0.5) diff-lcs (~> 1.0) ffi-yajl (>= 1.0, < 3.0) @@ -224,21 +226,21 @@ GEM minitar (~> 0.6) mixlib-cli (>= 1.7, < 3.0) mixlib-shellout (>= 2.0, < 4.0) - paint (~> 1.0) + paint (>= 1, < 3) solve (> 2.0, < 5.0) - chef-config (15.10.12) + chef-config (16.1.16) addressable - chef-utils (= 15.10.12) + chef-utils (= 16.1.16) fuzzyurl mixlib-config (>= 2.2.12, < 4.0) mixlib-shellout (>= 2.0, < 4.0) tomlrb (~> 1.2) - chef-telemetry (1.0.3) + chef-telemetry (1.0.8) chef-config concurrent-ruby (~> 1.0) ffi-yajl (~> 2.2) - http (~> 2.2) - chef-utils (15.10.12) + chef-utils (16.1.16) + chef-vault (4.0.1) chef-zero (15.0.0) ffi-yajl (~> 2.2) hashie (>= 2.0, < 5.0) @@ -246,7 +248,7 @@ GEM rack (~> 2.0, >= 2.0.6) uuidtools (~> 2.1) cleanroom (1.0.0) - coderay (1.1.2) + coderay (1.1.3) concurrent-ruby (1.1.6) cookbook-omnifetch (0.9.1) mixlib-archive (>= 0.4, < 2.0) @@ -272,7 +274,7 @@ GEM http-cookie (~> 1.0.0) faraday_middleware (0.12.2) faraday (>= 0.7.4, < 1.0) - ffi (1.12.2) + ffi (1.13.0) ffi-libarchive (1.0.0) ffi (~> 1.0) ffi-yajl (2.3.3) @@ -297,32 +299,25 @@ GEM ffi (>= 1.0.1) gyoku (1.3.1) builder (>= 2.1.2) - hana (1.3.5) + hana (1.3.6) hashie (3.6.0) - highline (1.7.10) + highline (2.0.3) htmlentities (4.3.4) - http (2.2.2) - addressable (~> 2.3) - http-cookie (~> 1.0) - http-form_data (~> 1.0.1) - http_parser.rb (~> 0.6.0) http-cookie (1.0.3) domain_name (~> 0.5) - http-form_data (1.0.3) - http_parser.rb (0.6.0) httpclient (2.8.3) i18n (1.8.2) concurrent-ruby (~> 1.0) inifile (3.0.0) iniparse (1.5.0) - inspec (4.18.104) + inspec (4.19.0) faraday_middleware (~> 0.12.2) - inspec-core (= 4.18.104) + inspec-core (= 4.19.0) train (~> 3.0) train-aws (~> 0.1) train-habitat (~> 0.1) train-winrm (~> 0.2) - inspec-core (4.18.104) + inspec-core (4.19.0) addressable (~> 2.4) chef-telemetry (~> 1.0) faraday (>= 0.9.0) @@ -330,12 +325,12 @@ GEM htmlentities (~> 4.3) json_schemer (~> 0.2.1) license-acceptance (>= 0.2.13, < 2.0) - method_source (~> 0.8) + method_source (>= 0.8, < 2.0) mixlib-log (~> 3.0) multipart-post (~> 2.0) parallel (~> 1.9) parslet (~> 1.5) - pry (~> 0) + pry (~> 0.13) rspec (~> 3.9) rspec-its (~> 1.2) rubyzip (~> 1.2, >= 1.2.2) @@ -356,7 +351,7 @@ GEM regexp_parser (~> 1.5) uri_template (~> 0.7) jwt (2.2.1) - kitchen-dokken (2.8.2) + kitchen-dokken (2.9.0) docker-api (~> 1.33) lockfile (~> 2.1) test-kitchen (>= 1.15, < 3) @@ -376,10 +371,10 @@ GEM little-plugger (~> 1.1) multi_json (~> 1.10) memoist (0.16.2) - method_source (0.9.2) + method_source (1.0.0) mini_mime (1.0.2) minitar (0.9) - minitest (5.14.0) + minitest (5.14.1) mixlib-archive (1.0.5) mixlib-log mixlib-authentication (3.0.6) @@ -398,12 +393,11 @@ GEM concurrent-ruby (~> 1.0) faraday (>= 0.9, < 2.0.0) timeliness (~> 0.3.10) - ms_rest_azure (0.11.2) + ms_rest_azure (0.12.0) concurrent-ruby (~> 1.0) faraday (>= 0.9, < 2.0.0) faraday-cookie_jar (~> 0.0.6) ms_rest (~> 0.7.6) - unf_ext (= 0.0.7.2) multi_json (1.14.1) multipart-post (2.1.1) necromancer (0.5.1) @@ -421,8 +415,9 @@ GEM octokit (4.18.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) - ohai (15.9.1) - chef-config (>= 12.8, < 16) + ohai (16.1.1) + chef-config (>= 12.8, < 17) + chef-utils (>= 16.0, < 17) ffi (~> 1.9) ffi-yajl (~> 2.2) ipaddress @@ -434,18 +429,18 @@ GEM systemu (~> 2.6.4) wmi-lite (~> 1.0) os (1.1.0) - paint (1.0.1) + paint (2.2.0) parallel (1.19.1) parslet (1.8.2) - pastel (0.7.3) + pastel (0.7.4) equatable (~> 0.6) tty-color (~> 0.5) plist (3.5.0) proxifier (1.0.3) - pry (0.12.2) - coderay (~> 1.1.0) - method_source (~> 0.9.0) - public_suffix (3.1.1) + pry (0.13.1) + coderay (~> 1.1) + method_source (~> 1.0) + public_suffix (4.0.5) rack (2.2.2) regexp_parser (1.7.0) representable (3.0.4) @@ -458,9 +453,9 @@ GEM rspec-core (~> 3.9.0) rspec-expectations (~> 3.9.0) rspec-mocks (~> 3.9.0) - rspec-core (3.9.1) - rspec-support (~> 3.9.1) - rspec-expectations (3.9.1) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) rspec-its (1.3.0) @@ -469,7 +464,7 @@ GEM rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) - rspec-support (3.9.2) + rspec-support (3.9.3) rubyntlm (0.6.2) rubyzip (1.3.0) sawyer (0.8.2) @@ -495,14 +490,14 @@ GEM systemu (2.6.5) term-ansicolor (1.7.1) tins (~> 1.0) - test-kitchen (2.4.0) + test-kitchen (2.5.1) bcrypt_pbkdf (~> 1.0) ed25519 (~> 1.2) license-acceptance (~> 1.0, >= 1.0.11) mixlib-install (~> 3.6) mixlib-shellout (>= 1.2, < 4.0) - net-scp (>= 1.1, < 3.0) - net-ssh (>= 2.9, < 6.0) + net-scp (>= 1.1, < 4.0) + net-ssh (>= 2.9, < 7.0) net-ssh-gateway (>= 1.2, < 3.0) thor (~> 0.19) winrm (~> 2.0) @@ -511,7 +506,7 @@ GEM thor (0.20.3) thread_safe (0.3.6) timeliness (0.3.10) - tins (1.24.1) + tins (1.25.0) sync tomlrb (1.3.0) train (3.2.28) @@ -599,7 +594,7 @@ GEM tty-cursor (~> 0.7) tty-screen (~> 0.7) wisper (~> 2.0.0) - tty-screen (0.7.1) + tty-screen (0.8.0) tty-table (0.11.0) equatable (~> 0.6) necromancer (~> 0.5) @@ -611,7 +606,7 @@ GEM uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.7.2) + unf_ext (0.0.7.7) unicode-display_width (1.7.0) unicode_utils (1.4.0) uri_template (0.7.0) From d7cc360fdbb13394615e0fe8cac9cd0b8e0ecdfd Mon Sep 17 00:00:00 2001 From: Cedric Alfonsi Date: Wed, 17 Jun 2020 14:38:40 +0200 Subject: [PATCH 006/287] Fix debian changelog for CE develop branch Signed-off-by: Cedric Alfonsi --- debian/changelog | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/changelog b/debian/changelog index d40595c858..ef48ee495e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -passbolt-pro-server (2.12.0-1) stretch; urgency=medium +passbolt-ce-server (2.12.1-1+beta) stretch; urgency=medium * Refactor config script * Refactor postinst script * Added questions for nginx setup @@ -11,13 +11,13 @@ passbolt-pro-server (2.12.0-1) stretch; urgency=medium -- Diego Lendoiro Thu, 21 May 2020 18:24:00 +0000 -passbolt-pro-server (2.12.0-0) stretch; urgency=medium +passbolt-ce-server (2.12.0-0) stretch; urgency=medium * Created an automated debian package -- Albert Casals Fri, 27 Dec 2019 01:15:00 +0100 -passbolt-pro-server (2.7.1-0) stretch; urgency=medium +passbolt-ce-server (2.7.1-0) stretch; urgency=medium * Initial release. From 52ef89c6a5f48d818302608f51cb854021cb92af Mon Sep 17 00:00:00 2001 From: Cedric Alfonsi Date: Tue, 23 Jun 2020 16:53:43 +0200 Subject: [PATCH 007/287] Update appjs to the latest version Signed-off-by: Cedric Alfonsi --- webroot/js/app/bundles/passbolt-appjs/passbolt.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webroot/js/app/bundles/passbolt-appjs/passbolt.js b/webroot/js/app/bundles/passbolt-appjs/passbolt.js index 5055eed966..49d8119336 100644 --- a/webroot/js/app/bundles/passbolt-appjs/passbolt.js +++ b/webroot/js/app/bundles/passbolt-appjs/passbolt.js @@ -1 +1 @@ -System.bundles={},define("npm-utils",function(e,t,a){!function(e,t,a,n){var r=Array.prototype.slice,s=/.+@.+\..+\..+#.+/,o=/#\{[^\}]+\}|#\?.+$/,i=/(git|http(s?)):\/\//,l="function"==typeof Set,c={extend:function(e,t,a,n){var s,o=n;if(a)if(o||(o=l?new Set:[]),l){if(o.has(t))return t;o.add(t)}else{if(-1!==o.indexOf(t))return t;o.push(t)}for(var i in t)s=t[i],a?c.isArray(s)?e[i]=r.call(s):c.isPlainObject(s)?e[i]=c.extend({},s,a,o):e[i]=t[i]:e[i]=t[i];return e},map:function(e,t){for(var a=0,n=e.length,r=[];a=0)return a>=0?e.substr(0,a):e},findDep:function(e,t,a){if(e.npm&&t&&!c.path.startsWithDotSlash(a)){var n=a+"@"+t.resolutions[a];return e.npm[n]}},findDepWalking:function(e,t,a){if(e.npm&&t&&!c.path.startsWithDotSlash(a))for(var n=c.path.depPackageDir(t.fileUrl,a);n;){var r=e.npmPaths[n];if(r)return r;var s=c.path.parentNodeModuleAddress(n);if(!s)return;n=s+"/"+a}},findByName:function(e,t){if(e.npm&&!c.path.startsWithDotSlash(t))return e.npm[t]},findByNameAndVersion:function(e,t,a){if(e.npm&&!c.path.startsWithDotSlash(t)){var n=t+"@"+a;return e.npm[n]}},findByUrl:function(e,t){if(e.npm){var a=c.pkg.folderAddress(t);return e.npmPaths[a]}},directoriesLib:function(e){var t,a=c.pkg.config(e),n=a&&a.directories&&a.directories.lib,r=[".","/"];if(n){for(;t=r.shift();)n[0]===t&&(n=n.substr(1));return n}},hasDirectoriesLib:function(e){var t=c.pkg.config(e);return t&&t.directories&&!!t.directories.lib},findPackageInfo:function(e,t){var a,n=e.pkgInfo;if(n)return c.forEach(n,function(e){t.name===e.name&&t.version===e.version&&(a=e)}),a},saveResolution:function(e,t,a){c.pkg.findPackageInfo(e,t).resolutions[a.name]=t.resolutions[a.name]=a.version},config:function(e){return e.steal||e.system}},path:{makeRelative:function(e){return c.path.isRelative(e)&&"/"!==e.substr(0,1)?e:"./"+e},removeJS:function(e){return e.replace(/\.js(!|$)/,function(e,t){return t})},removePackage:function(e){return e.replace(/\/package\.json.*/,"")},addJS:function(e){return/\.m?js(on)?$/.test(e)?e:e+".js"},isRelative:function(e){return"."===e.substr(0,1)},isInHomeDir:function(e,t){return e.substr(0,2)===c.pkg.homeAlias(t)+"/"},joinURIs:function(e,t){var a,n,r=u(t||""),s=u(e||"");return r&&s?(r.protocol||s.protocol)+(r.protocol||r.authority?r.authority:s.authority)+(a=r.protocol||r.authority||"/"===r.pathname.charAt(0)?r.pathname:r.pathname?(s.authority&&!s.pathname?"/":"")+s.pathname.slice(0,s.pathname.lastIndexOf("/")+1)+r.pathname:s.pathname,n=[],a.replace(/^(\.\.?(\/|$))+/,"").replace(/\/(\.(\/|$))+/g,"/").replace(/\/\.\.$/,"/../").replace(/\/?[^\/]*/g,function(e){"/.."===e?n.pop():n.push(e)}),n.join("").replace(/^\//,"/"===a.charAt(0)?"/":""))+(r.protocol||r.authority||r.pathname?r.search:r.search||s.search)+r.hash:null},startsWithDotSlash:function(e){return"./"===e.substr(0,2)},removeDotSlash:function(e){return c.path.startsWithDotSlash(e)?e.substr(2):e},endsWithSlash:function(e){return"/"===e[e.length-1]},addEndingSlash:function(e){return c.path.endsWithSlash(e)?e:e+"/"},depPackage:function(e,t){var a=e.replace(/\/package\.json.*/,"");return(a?a+"/":"")+"node_modules/"+t+"/package.json"},peerPackage:function(e,t){var a=e.replace(/\/package\.json.*/,"");return a.substr(0,a.lastIndexOf("/"))+"/"+t+"/package.json"},depPackageDir:function(e,t){return c.path.depPackage(e,t).replace(/\/package\.json.*/,"")},peerNodeModuleAddress:function(e){var t=e.lastIndexOf("/node_modules/");if(t>=0)return e.substr(0,t+"/node_modules/".length-1)},parentNodeModuleAddress:function(e){var t=e.lastIndexOf("/node_modules/"),a=e.lastIndexOf("/node_modules/",t-1);if(a>=0)return e.substr(0,a+"/node_modules/".length-1)},pkgDir:function(e){var t=e.lastIndexOf("/node_modules/"),a=e.indexOf("/",t+"/node_modules/".length);if("@"===e[t+"/node_modules/".length]&&(a=e.indexOf("/",a+1)),t>=0)return a>=0?e.substr(0,a):e},basename:function(e){var t=e.split("/");return t[t.length-1]},relativeTo:function(e,t){for(var a=e.split("/"),n=1;"."===t[n];)a.pop(),n++;return a.join("/")},isPackageRootDir:function(e){return-1===e.indexOf("/")}},json:{transform:function(e,t,a){a.steal=c.pkg.config(a);var n=e.jsonOptions&&e.jsonOptions.transform;return n?n.call(e,t,a):a}},includeInBuild:!0};function u(e){var t=String(e).replace(/^\s+|\s+$/g,"").match(/^([^:\/?#]+:)?(\/\/(?:[^:@\/]*(?::[^:@\/]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);return t?{href:t[0]||"",protocol:t[1]||"",authority:t[2]||"",host:t[3]||"",hostname:t[4]||"",port:t[5]||"",pathname:t[6]||"",search:t[7]||"",hash:t[8]||""}:null}n.exports=c}(0,0,0,a)}),define("npm-extension",["require","exports","module","@steal","./npm-utils"],function(e,t,a){!function(e,t,a,n){var r=t("@steal"),s=t("./npm-utils");a.includeInBuild=!0;var o="object"==typeof process&&"[object process]"==={}.toString.call(process),i="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope,l=o&&!!process.versions.electron,c="undefined"!=typeof window&&(!o||l)&&!i;a.addExtension=function e(t){t._extensions&&t._extensions.push(e);var a=t.normalize;t.normalize=function(e,t,n,r){var o=e,i=t;i&&this.npmParentMap&&this.npmParentMap[i]&&(i=this.npmParentMap[i]);var l=s.path.isRelative(o),c=s.moduleName.isNpm(o),u=s.moduleName.isNpm(i),p=s.path.endsWithSlash(o);if(c&&t)return a.call(this,o,i,n,r);if(i&&l&&!u)return a.call(this,o,i,n,r);if(s.moduleName.isConditional(o))return a.call(this,o,i,n,r);if("object"==typeof this.map[i]&&this.map[i][o])return a.call(this,o,i,n,r);var d=s.pkg.findByModuleNameOrAddress(this,i,n);if(!d)return a.call(this,o,i,n,r);if(u&&("../"===o||"./"===o)){var f=s.moduleName.parse(i).modulePath||"",g=s.path.relativeTo(f,o);s.path.isPackageRootDir(g)?o=d.name+"#"+s.path.removeJS(s.path.removeDotSlash(d.main)):o+="index"}var h,m,y=s.moduleName.parseFromPackage(this,d,o,i),k=s.pkg.isRoot(this,d),v=y.packageName===d.name;u&&l&&v&&(h=d);var T=this.npmContext,b=T&&T.crawl,_=!!b;if(!h)if(b){if((x=l?null:b.matchedVersion(T,d.name,d.version))&&(m=b.getFullDependencyMap(this,x,k)[y.packageName])){var w=d.resolutions&&d.resolutions[m.name]||m.version,S=b.matchedVersion(this.npmContext,m.name,w);S&&(h=s.pkg.findByUrl(this,S.fileUrl))}}else h=k?s.pkg.findDepWalking(this,d,y.packageName):s.pkg.findDep(this,d,y.packageName);if(v&&(h=s.pkg.findByNameAndVersion(this,y.packageName,d.version)),y.isGlobal,h||(h=s.pkg.findByName(this,y.packageName)),_&&h&&m&&!b.pkgSatisfies(h,m.version)?h=void 0:_&&h&&s.pkg.saveResolution(T,d,h),!h){var E=this.globalBrowser[y.packageName];E&&(y.packageName=E.moduleName,h=s.pkg.findByName(this,y.packageName))}if(!h&&k&&o===d.main&&s.pkg.hasDirectoriesLib(d))return y.version=d.version,y.packageName=d.name,y.modulePath=s.pkg.main(d),a.call(this,s.moduleName.create(y),i,n,r);var x,j=this;if(h)return M(h);if(b&&(x=b.matchedVersion(this.npmContext,d.name,d.version))&&!(h=b.getFullDependencyMap(this,x,k)[y.packageName])){var C=b.findPackageAndParents(this.npmContext,y.packageName);C&&(h=C.package)}if(!h){if(d.browser&&d.browser[o])return a.call(this,d.browser[o],i,n,r);var A=s.pkg.config(d);if(A&&A.map&&"string"==typeof A.map[o]){var V=A.map[o],P=A.envs&&A.envs[j.env];return P&&P.map&&"string"==typeof P.map[o]&&(V=P.map[o]),j.normalize(V,i,n,r)}return a.call(this,o,i,n,r)}return b.dep(this.npmContext,x,d,h,k).then(M);function M(e){y.version=e.version,y.modulePath||(y.modulePath=s.pkg.main(e));var t=a.call(j,s.moduleName.create(y),i,n,r);return p&&t.then(function(e){T&&T.forwardSlashMap&&(T.forwardSlashMap[e]=!0)}),t}};var n=t.locate;t.locate=function(e){var a=s.moduleName.parse(e.name),o=this,i=e.metadata.parsedModuleName=a;if(e.metadata.npmPackage=s.pkg.findByNameAndVersion(this,i.packageName,i.version),a.version&&this.npm&&!o.paths[e.name]){var l=this.npm[s.moduleName.nameAndVersion(a)];if(l)return n.call(this,e).then(function(n){var i=n,u=s.path.joinURIs(t.baseURL,e.name);if(c&&(u=u.replace(/#/g,"%23")),i!==u+".js"&&i!==u)return i;var p=s.pkg.rootDir(l,s.pkg.isRoot(o,l));if(a.modulePath){var d=s.path.joinURIs(s.path.addEndingSlash(p),a.plugin?a.modulePath:s.path.addJS(a.modulePath));i=void 0!==r?s.path.joinURIs(o.baseURL,d):d}return i})}return n.call(this,e)};var i=t.fetch;t.fetch=function(e){if(e.metadata.dryRun)return i.apply(this,arguments);var t=this,a=(t.npmContext,Promise.resolve(i.apply(this,arguments)));return s.moduleName.isNpm(e.name)&&(a=a.then(null,function(a){var n=a.statusCode;return 404!==n&&0!==n?Promise.reject(a):(t.npmContext||(t.npmContext={forwardSlashMap:{}}),function a(n,r){if(!n.length)throw r;var i=n.shift();if(!i.test(e))throw r;return Promise.resolve(function(e,t){var a=this,n="function"==typeof t.name?t.name(a,e):e.name+t.name,r=s.extend({},e);return r.name=n,r.metadata={dryRun:!0},Promise.resolve(a.locate(r)).then(function(e){return r.address=e,a.fetch(r)}).then(function(t){e.metadata.address=r.address,a.npmParentMap[e.name]=r.name;var n=a.npmContext&&a.npmContext.npmLoad;return n&&(n.saveLoadIfNeeded(a.npmContext),o||s.warnOnce("Some 404s were encountered while loading. Don't panic! These will only happen in dev and are harmless.")),t})}.call(t,e,i)).then(null,function(e){return a(n,e)})}([].slice.call(f),a).then(null,function(e){return Promise.reject(a)}))})),a.catch(function(a){var n=a.statusCode;if(404!==n&&0!==n||!s.moduleName.isBareIdentifier(e.name)||s.pkg.isRoot(t,e.metadata.npmPackage))throw a;var r=new Error(["Could not load '"+e.name+"'","Is this an npm module not saved in your package.json?"].join("\n"));throw r.statusCode=a.statusCode,r.stack=r.stack+a.stack,r})};var l=function(e,t){var a=s.pkg.findByName(e,t.split("/")[0]);if(a){var n=s.moduleName.parse(t,a.name);return n.version=a.version,n.modulePath||(n.modulePath=s.pkg.main(a)),s.moduleName.create(n)}return t},u={map:function(e){var t,a={};for(var n in e)t=e[n],a[l(this,n)]="object"==typeof t?u.map(t):l(this,t);return a},meta:function(e){var t={};for(var a in e)t[l(this,a)]=e[a];return t},paths:function(e){var t={};for(var a in e)t[l(this,a)]=e[a];return t}},p=t.config;t.config=function(e){if(this.npmContext){var t=this.npmContext,a=t.versions.__default,n=t.convert.steal(t,a,e,!0);return t.convert.updateConfigOnPackageLoad(n,!1,!0,t.applyBuildConfig),void p.apply(this,arguments)}for(var r in e)u[r]&&(e[r]=u[r].call(this,e[r]));p.apply(this,arguments)};var d=t._newLoader||Function.prototype;t._newLoader=function(e){return e.npmContext=this.npmContext,e.npmParentMap=this.npmParentMap,d.apply(this,arguments)},r.addNpmPackages=function(e){for(var t=e||[],a=this.loader,n=0;n0&&t-1 in e)}T.fn=T.prototype={jquery:"3.5.0",constructor:T,length:0,toArray:function(){return r.call(this)},get:function(e){return null==e?r.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=T.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return T.each(this,e)},map:function(e){return this.pushStack(T.map(this,function(t,a){return e.call(t,a,t)}))},slice:function(){return this.pushStack(r.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(T.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(T.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,a=+e+(e<0?t:0);return this.pushStack(a>=0&&a+~]|"+R+")"+R+"*"),G=new RegExp(R+"|>"),K=new RegExp(F),W=new RegExp("^"+q+"$"),Y={ID:new RegExp("^#("+q+")"),CLASS:new RegExp("^\\.("+q+")"),TAG:new RegExp("^("+q+"|[*])"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},$=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,J=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+R+"?|\\\\([^\\r\\n\\f])","g"),ae=function(e,t){var a="0x"+e.slice(1)-65536;return t||(a<0?String.fromCharCode(a+65536):String.fromCharCode(a>>10|55296,1023&a|56320))},ne=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,re=function(e,t){return t?"\0"===e?"�":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},se=function(){d()},oe=Te(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{D.apply(V=O.call(b.childNodes),b.childNodes),V[b.childNodes.length].nodeType}catch(e){D={apply:V.length?function(e,t){M.apply(e,O.call(t))}:function(e,t){for(var a=e.length,n=0;e[a++]=t[n++];);e.length=a-1}}}function ie(e,t,n,r){var s,i,c,u,p,g,y,k=t&&t.ownerDocument,b=t?t.nodeType:9;if(n=n||[],"string"!=typeof e||!e||1!==b&&9!==b&&11!==b)return n;if(!r&&(d(t),t=t||f,h)){if(11!==b&&(p=Z.exec(e)))if(s=p[1]){if(9===b){if(!(c=t.getElementById(s)))return n;if(c.id===s)return n.push(c),n}else if(k&&(c=k.getElementById(s))&&v(t,c)&&c.id===s)return n.push(c),n}else{if(p[2])return D.apply(n,t.getElementsByTagName(e)),n;if((s=p[3])&&a.getElementsByClassName&&t.getElementsByClassName)return D.apply(n,t.getElementsByClassName(s)),n}if(a.qsa&&!j[e+" "]&&(!m||!m.test(e))&&(1!==b||"object"!==t.nodeName.toLowerCase())){if(y=e,k=t,1===b&&(G.test(e)||H.test(e))){for((k=ee.test(e)&&ye(t.parentNode)||t)===t&&a.scope||((u=t.getAttribute("id"))?u=u.replace(ne,re):t.setAttribute("id",u=T)),i=(g=o(e)).length;i--;)g[i]=(u?"#"+u:":scope")+" "+ve(g[i]);y=g.join(",")}try{return D.apply(n,k.querySelectorAll(y)),n}catch(t){j(e,!0)}finally{u===T&&t.removeAttribute("id")}}}return l(e.replace(z,"$1"),t,n,r)}function le(){var e=[];return function t(a,r){return e.push(a+" ")>n.cacheLength&&delete t[e.shift()],t[a+" "]=r}}function ce(e){return e[T]=!0,e}function ue(e){var t=f.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function pe(e,t){for(var a=e.split("|"),r=a.length;r--;)n.attrHandle[a[r]]=t}function de(e,t){var a=t&&e,n=a&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(n)return n;if(a)for(;a=a.nextSibling;)if(a===t)return-1;return e?1:-1}function fe(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function ge(e){return function(t){var a=t.nodeName.toLowerCase();return("input"===a||"button"===a)&&t.type===e}}function he(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&oe(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function me(e){return ce(function(t){return t=+t,ce(function(a,n){for(var r,s=e([],a.length,t),o=s.length;o--;)a[r=s[o]]&&(a[r]=!(n[r]=a[r]))})})}function ye(e){return e&&void 0!==e.getElementsByTagName&&e}for(t in a=ie.support={},s=ie.isXML=function(e){var t=e.namespaceURI,a=(e.ownerDocument||e).documentElement;return!$.test(t||a&&a.nodeName||"HTML")},d=ie.setDocument=function(e){var t,r,o=e?e.ownerDocument||e:b;return o!=f&&9===o.nodeType&&o.documentElement?(g=(f=o).documentElement,h=!s(f),b!=f&&(r=f.defaultView)&&r.top!==r&&(r.addEventListener?r.addEventListener("unload",se,!1):r.attachEvent&&r.attachEvent("onunload",se)),a.scope=ue(function(e){return g.appendChild(e).appendChild(f.createElement("div")),void 0!==e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),a.attributes=ue(function(e){return e.className="i",!e.getAttribute("className")}),a.getElementsByTagName=ue(function(e){return e.appendChild(f.createComment("")),!e.getElementsByTagName("*").length}),a.getElementsByClassName=J.test(f.getElementsByClassName),a.getById=ue(function(e){return g.appendChild(e).id=T,!f.getElementsByName||!f.getElementsByName(T).length}),a.getById?(n.filter.ID=function(e){var t=e.replace(te,ae);return function(e){return e.getAttribute("id")===t}},n.find.ID=function(e,t){if(void 0!==t.getElementById&&h){var a=t.getElementById(e);return a?[a]:[]}}):(n.filter.ID=function(e){var t=e.replace(te,ae);return function(e){var a=void 0!==e.getAttributeNode&&e.getAttributeNode("id");return a&&a.value===t}},n.find.ID=function(e,t){if(void 0!==t.getElementById&&h){var a,n,r,s=t.getElementById(e);if(s){if((a=s.getAttributeNode("id"))&&a.value===e)return[s];for(r=t.getElementsByName(e),n=0;s=r[n++];)if((a=s.getAttributeNode("id"))&&a.value===e)return[s]}return[]}}),n.find.TAG=a.getElementsByTagName?function(e,t){return void 0!==t.getElementsByTagName?t.getElementsByTagName(e):a.qsa?t.querySelectorAll(e):void 0}:function(e,t){var a,n=[],r=0,s=t.getElementsByTagName(e);if("*"===e){for(;a=s[r++];)1===a.nodeType&&n.push(a);return n}return s},n.find.CLASS=a.getElementsByClassName&&function(e,t){if(void 0!==t.getElementsByClassName&&h)return t.getElementsByClassName(e)},y=[],m=[],(a.qsa=J.test(f.querySelectorAll))&&(ue(function(e){var t;g.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&m.push("[*^$]="+R+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||m.push("\\["+R+"*(?:value|"+L+")"),e.querySelectorAll("[id~="+T+"-]").length||m.push("~="),(t=f.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||m.push("\\["+R+"*name"+R+"*="+R+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||m.push(":checked"),e.querySelectorAll("a#"+T+"+*").length||m.push(".#.+[+~]"),e.querySelectorAll("\\\f"),m.push("[\\r\\n\\f]")}),ue(function(e){e.innerHTML="";var t=f.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&m.push("name"+R+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&m.push(":enabled",":disabled"),g.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&m.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),m.push(",.*:")})),(a.matchesSelector=J.test(k=g.matches||g.webkitMatchesSelector||g.mozMatchesSelector||g.oMatchesSelector||g.msMatchesSelector))&&ue(function(e){a.disconnectedMatch=k.call(e,"*"),k.call(e,"[s!='']:x"),y.push("!=",F)}),m=m.length&&new RegExp(m.join("|")),y=y.length&&new RegExp(y.join("|")),t=J.test(g.compareDocumentPosition),v=t||J.test(g.contains)?function(e,t){var a=9===e.nodeType?e.documentElement:e,n=t&&t.parentNode;return e===n||!(!n||1!==n.nodeType||!(a.contains?a.contains(n):e.compareDocumentPosition&&16&e.compareDocumentPosition(n)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},C=t?function(e,t){if(e===t)return p=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!a.sortDetached&&t.compareDocumentPosition(e)===n?e==f||e.ownerDocument==b&&v(b,e)?-1:t==f||t.ownerDocument==b&&v(b,t)?1:u?I(u,e)-I(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return p=!0,0;var a,n=0,r=e.parentNode,s=t.parentNode,o=[e],i=[t];if(!r||!s)return e==f?-1:t==f?1:r?-1:s?1:u?I(u,e)-I(u,t):0;if(r===s)return de(e,t);for(a=e;a=a.parentNode;)o.unshift(a);for(a=t;a=a.parentNode;)i.unshift(a);for(;o[n]===i[n];)n++;return n?de(o[n],i[n]):o[n]==b?-1:i[n]==b?1:0},f):f},ie.matches=function(e,t){return ie(e,null,null,t)},ie.matchesSelector=function(e,t){if(d(e),a.matchesSelector&&h&&!j[t+" "]&&(!y||!y.test(t))&&(!m||!m.test(t)))try{var n=k.call(e,t);if(n||a.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){j(t,!0)}return ie(t,f,null,[e]).length>0},ie.contains=function(e,t){return(e.ownerDocument||e)!=f&&d(e),v(e,t)},ie.attr=function(e,t){(e.ownerDocument||e)!=f&&d(e);var r=n.attrHandle[t.toLowerCase()],s=r&&A.call(n.attrHandle,t.toLowerCase())?r(e,t,!h):void 0;return void 0!==s?s:a.attributes||!h?e.getAttribute(t):(s=e.getAttributeNode(t))&&s.specified?s.value:null},ie.escape=function(e){return(e+"").replace(ne,re)},ie.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},ie.uniqueSort=function(e){var t,n=[],r=0,s=0;if(p=!a.detectDuplicates,u=!a.sortStable&&e.slice(0),e.sort(C),p){for(;t=e[s++];)t===e[s]&&(r=n.push(s));for(;r--;)e.splice(n[r],1)}return u=null,e},r=ie.getText=function(e){var t,a="",n=0,s=e.nodeType;if(s){if(1===s||9===s||11===s){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)a+=r(e)}else if(3===s||4===s)return e.nodeValue}else for(;t=e[n++];)a+=r(t);return a},(n=ie.selectors={cacheLength:50,createPseudo:ce,match:Y,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ae),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ae),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ie.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ie.error(e[0]),e},PSEUDO:function(e){var t,a=!e[6]&&e[2];return Y.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":a&&K.test(a)&&(t=o(a,!0))&&(t=a.indexOf(")",a.length-t)-a.length)&&(e[0]=e[0].slice(0,t),e[2]=a.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ae).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=S[e+" "];return t||(t=new RegExp("(^|"+R+")"+e+"("+R+"|$)"))&&S(e,function(e){return t.test("string"==typeof e.className&&e.className||void 0!==e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,t,a){return function(n){var r=ie.attr(n,e);return null==r?"!="===t:!t||(r+="","="===t?r===a:"!="===t?r!==a:"^="===t?a&&0===r.indexOf(a):"*="===t?a&&r.indexOf(a)>-1:"$="===t?a&&r.slice(-a.length)===a:"~="===t?(" "+r.replace(U," ")+" ").indexOf(a)>-1:"|="===t&&(r===a||r.slice(0,a.length+1)===a+"-"))}},CHILD:function(e,t,a,n,r){var s="nth"!==e.slice(0,3),o="last"!==e.slice(-4),i="of-type"===t;return 1===n&&0===r?function(e){return!!e.parentNode}:function(t,a,l){var c,u,p,d,f,g,h=s!==o?"nextSibling":"previousSibling",m=t.parentNode,y=i&&t.nodeName.toLowerCase(),k=!l&&!i,v=!1;if(m){if(s){for(;h;){for(d=t;d=d[h];)if(i?d.nodeName.toLowerCase()===y:1===d.nodeType)return!1;g=h="only"===e&&!g&&"nextSibling"}return!0}if(g=[o?m.firstChild:m.lastChild],o&&k){for(v=(f=(c=(u=(p=(d=m)[T]||(d[T]={}))[d.uniqueID]||(p[d.uniqueID]={}))[e]||[])[0]===_&&c[1])&&c[2],d=f&&m.childNodes[f];d=++f&&d&&d[h]||(v=f=0)||g.pop();)if(1===d.nodeType&&++v&&d===t){u[e]=[_,f,v];break}}else if(k&&(v=f=(c=(u=(p=(d=t)[T]||(d[T]={}))[d.uniqueID]||(p[d.uniqueID]={}))[e]||[])[0]===_&&c[1]),!1===v)for(;(d=++f&&d&&d[h]||(v=f=0)||g.pop())&&((i?d.nodeName.toLowerCase()!==y:1!==d.nodeType)||!++v||(k&&((u=(p=d[T]||(d[T]={}))[d.uniqueID]||(p[d.uniqueID]={}))[e]=[_,v]),d!==t)););return(v-=r)===n||v%n==0&&v/n>=0}}},PSEUDO:function(e,t){var a,r=n.pseudos[e]||n.setFilters[e.toLowerCase()]||ie.error("unsupported pseudo: "+e);return r[T]?r(t):r.length>1?(a=[e,e,"",t],n.setFilters.hasOwnProperty(e.toLowerCase())?ce(function(e,a){for(var n,s=r(e,t),o=s.length;o--;)e[n=I(e,s[o])]=!(a[n]=s[o])}):function(e){return r(e,0,a)}):r}},pseudos:{not:ce(function(e){var t=[],a=[],n=i(e.replace(z,"$1"));return n[T]?ce(function(e,t,a,r){for(var s,o=n(e,null,r,[]),i=e.length;i--;)(s=o[i])&&(e[i]=!(t[i]=s))}):function(e,r,s){return t[0]=e,n(t,null,s,a),t[0]=null,!a.pop()}}),has:ce(function(e){return function(t){return ie(e,t).length>0}}),contains:ce(function(e){return e=e.replace(te,ae),function(t){return(t.textContent||r(t)).indexOf(e)>-1}}),lang:ce(function(e){return W.test(e||"")||ie.error("unsupported lang: "+e),e=e.replace(te,ae).toLowerCase(),function(t){var a;do{if(a=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(a=a.toLowerCase())===e||0===a.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var a=e.location&&e.location.hash;return a&&a.slice(1)===t.id},root:function(e){return e===g},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:he(!1),disabled:he(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!n.pseudos.empty(e)},header:function(e){return X.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:me(function(){return[0]}),last:me(function(e,t){return[t-1]}),eq:me(function(e,t,a){return[a<0?a+t:a]}),even:me(function(e,t){for(var a=0;at?t:a;--n>=0;)e.push(n);return e}),gt:me(function(e,t,a){for(var n=a<0?a+t:a;++n1?function(t,a,n){for(var r=e.length;r--;)if(!e[r](t,a,n))return!1;return!0}:e[0]}function _e(e,t,a,n,r){for(var s,o=[],i=0,l=e.length,c=null!=t;i-1&&(s[c]=!(o[c]=p))}}else y=_e(y===o?y.splice(g,y.length):y),r?r(null,o,y,l):D.apply(o,y)})}function Se(e){for(var t,a,r,s=e.length,o=n.relative[e[0].type],i=o||n.relative[" "],l=o?1:0,u=Te(function(e){return e===t},i,!0),p=Te(function(e){return I(t,e)>-1},i,!0),d=[function(e,a,n){var r=!o&&(n||a!==c)||((t=a).nodeType?u(e,a,n):p(e,a,n));return t=null,r}];l1&&be(d),l>1&&ve(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),a,l0,r=e.length>0,s=function(s,o,i,l,u){var p,g,m,y=0,k="0",v=s&&[],T=[],b=c,w=s||r&&n.find.TAG("*",u),S=_+=null==b?1:Math.random()||.1,E=w.length;for(u&&(c=o==f||o||u);k!==E&&null!=(p=w[k]);k++){if(r&&p){for(g=0,o||p.ownerDocument==f||(d(p),i=!h);m=e[g++];)if(m(p,o||f,i)){l.push(p);break}u&&(_=S)}a&&((p=!m&&p)&&y--,s&&v.push(p))}if(y+=k,a&&k!==y){for(g=0;m=t[g++];)m(v,T,o,i);if(s){if(y>0)for(;k--;)v[k]||T[k]||(T[k]=P.call(l));T=_e(T)}D.apply(l,T),u&&!s&&T.length>0&&y+t.length>1&&ie.uniqueSort(l)}return u&&(_=S,c=b),v};return a?ce(s):s}(s,r))).selector=e}return i},l=ie.select=function(e,t,a,r){var s,l,c,u,p,d="function"==typeof e&&e,f=!r&&o(e=d.selector||e);if(a=a||[],1===f.length){if((l=f[0]=f[0].slice(0)).length>2&&"ID"===(c=l[0]).type&&9===t.nodeType&&h&&n.relative[l[1].type]){if(!(t=(n.find.ID(c.matches[0].replace(te,ae),t)||[])[0]))return a;d&&(t=t.parentNode),e=e.slice(l.shift().value.length)}for(s=Y.needsContext.test(e)?0:l.length;s--&&(c=l[s],!n.relative[u=c.type]);)if((p=n.find[u])&&(r=p(c.matches[0].replace(te,ae),ee.test(l[0].type)&&ye(t.parentNode)||t))){if(l.splice(s,1),!(e=r.length&&ve(l)))return D.apply(a,r),a;break}}return(d||i(e,f))(r,t,!h,a,!t||ee.test(e)&&ye(t.parentNode)||t),a},a.sortStable=T.split("").sort(C).join("")===T,a.detectDuplicates=!!p,d(),a.sortDetached=ue(function(e){return 1&e.compareDocumentPosition(f.createElement("fieldset"))}),ue(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||pe("type|href|height|width",function(e,t,a){if(!a)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),a.attributes&&ue(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||pe("value",function(e,t,a){if(!a&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ue(function(e){return null==e.getAttribute("disabled")})||pe(L,function(e,t,a){var n;if(!a)return!0===e[t]?t.toLowerCase():(n=e.getAttributeNode(t))&&n.specified?n.value:null}),ie}(e);T.find=_,T.expr=_.selectors,T.expr[":"]=T.expr.pseudos,T.uniqueSort=T.unique=_.uniqueSort,T.text=_.getText,T.isXMLDoc=_.isXML,T.contains=_.contains,T.escapeSelector=_.escape;var w=function(e,t,a){for(var n=[],r=void 0!==a;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(r&&T(e).is(a))break;n.push(e)}return n},S=function(e,t){for(var a=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&a.push(e);return a},E=T.expr.match.needsContext;function x(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var j=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function C(e,t,a){return g(t)?T.grep(e,function(e,n){return!!t.call(e,n,e)!==a}):t.nodeType?T.grep(e,function(e){return e===t!==a}):"string"!=typeof t?T.grep(e,function(e){return i.call(t,e)>-1!==a}):T.filter(t,e,a)}T.filter=function(e,t,a){var n=t[0];return a&&(e=":not("+e+")"),1===t.length&&1===n.nodeType?T.find.matchesSelector(n,e)?[n]:[]:T.find.matches(e,T.grep(t,function(e){return 1===e.nodeType}))},T.fn.extend({find:function(e){var t,a,n=this.length,r=this;if("string"!=typeof e)return this.pushStack(T(e).filter(function(){for(t=0;t1?T.uniqueSort(a):a},filter:function(e){return this.pushStack(C(this,e||[],!1))},not:function(e){return this.pushStack(C(this,e||[],!0))},is:function(e){return!!C(this,"string"==typeof e&&E.test(e)?T(e):e||[],!1).length}});var A,V=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(T.fn.init=function(e,t,a){var n,r;if(!e)return this;if(a=a||A,"string"==typeof e){if(!(n="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:V.exec(e))||!n[1]&&t)return!t||t.jquery?(t||a).find(e):this.constructor(t).find(e);if(n[1]){if(t=t instanceof T?t[0]:t,T.merge(this,T.parseHTML(n[1],t&&t.nodeType?t.ownerDocument||t:m,!0)),j.test(n[1])&&T.isPlainObject(t))for(n in t)g(this[n])?this[n](t[n]):this.attr(n,t[n]);return this}return(r=m.getElementById(n[2]))&&(this[0]=r,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):g(e)?void 0!==a.ready?a.ready(e):e(T):T.makeArray(e,this)}).prototype=T.fn,A=T(m);var P=/^(?:parents|prev(?:Until|All))/,M={children:!0,contents:!0,next:!0,prev:!0};function D(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}T.fn.extend({has:function(e){var t=T(e,this),a=t.length;return this.filter(function(){for(var e=0;e-1:1===a.nodeType&&T.find.matchesSelector(a,e))){s.push(a);break}return this.pushStack(s.length>1?T.uniqueSort(s):s)},index:function(e){return e?"string"==typeof e?i.call(T(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(T.uniqueSort(T.merge(this.get(),T(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),T.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return w(e,"parentNode")},parentsUntil:function(e,t,a){return w(e,"parentNode",a)},next:function(e){return D(e,"nextSibling")},prev:function(e){return D(e,"previousSibling")},nextAll:function(e){return w(e,"nextSibling")},prevAll:function(e){return w(e,"previousSibling")},nextUntil:function(e,t,a){return w(e,"nextSibling",a)},prevUntil:function(e,t,a){return w(e,"previousSibling",a)},siblings:function(e){return S((e.parentNode||{}).firstChild,e)},children:function(e){return S(e.firstChild)},contents:function(e){return null!=e.contentDocument&&n(e.contentDocument)?e.contentDocument:(x(e,"template")&&(e=e.content||e),T.merge([],e.childNodes))}},function(e,t){T.fn[e]=function(a,n){var r=T.map(this,t,a);return"Until"!==e.slice(-5)&&(n=a),n&&"string"==typeof n&&(r=T.filter(n,r)),this.length>1&&(M[e]||T.uniqueSort(r),P.test(e)&&r.reverse()),this.pushStack(r)}});var O=/[^\x20\t\r\n\f]+/g;function I(e){return e}function L(e){throw e}function R(e,t,a,n){var r;try{e&&g(r=e.promise)?r.call(e).done(t).fail(a):e&&g(r=e.then)?r.call(e,t,a):t.apply(void 0,[e].slice(n))}catch(e){a.apply(void 0,[e])}}T.Callbacks=function(e){e="string"==typeof e?function(e){var t={};return T.each(e.match(O)||[],function(e,a){t[a]=!0}),t}(e):T.extend({},e);var t,a,n,r,s=[],o=[],i=-1,l=function(){for(r=r||e.once,n=t=!0;o.length;i=-1)for(a=o.shift();++i-1;)s.splice(a,1),a<=i&&i--}),this},has:function(e){return e?T.inArray(e,s)>-1:s.length>0},empty:function(){return s&&(s=[]),this},disable:function(){return r=o=[],s=a="",this},disabled:function(){return!s},lock:function(){return r=o=[],a||t||(s=a=""),this},locked:function(){return!!r},fireWith:function(e,a){return r||(a=[e,(a=a||[]).slice?a.slice():a],o.push(a),t||l()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},T.extend({Deferred:function(t){var a=[["notify","progress",T.Callbacks("memory"),T.Callbacks("memory"),2],["resolve","done",T.Callbacks("once memory"),T.Callbacks("once memory"),0,"resolved"],["reject","fail",T.Callbacks("once memory"),T.Callbacks("once memory"),1,"rejected"]],n="pending",r={state:function(){return n},always:function(){return s.done(arguments).fail(arguments),this},catch:function(e){return r.then(null,e)},pipe:function(){var e=arguments;return T.Deferred(function(t){T.each(a,function(a,n){var r=g(e[n[4]])&&e[n[4]];s[n[1]](function(){var e=r&&r.apply(this,arguments);e&&g(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[n[0]+"With"](this,r?[e]:arguments)})}),e=null}).promise()},then:function(t,n,r){var s=0;function o(t,a,n,r){return function(){var i=this,l=arguments,c=function(){var e,c;if(!(t=s&&(n!==L&&(i=void 0,l=[e]),a.rejectWith(i,l))}};t?u():(T.Deferred.getStackHook&&(u.stackTrace=T.Deferred.getStackHook()),e.setTimeout(u))}}return T.Deferred(function(e){a[0][3].add(o(0,e,g(r)?r:I,e.notifyWith)),a[1][3].add(o(0,e,g(t)?t:I)),a[2][3].add(o(0,e,g(n)?n:L))}).promise()},promise:function(e){return null!=e?T.extend(e,r):r}},s={};return T.each(a,function(e,t){var o=t[2],i=t[5];r[t[1]]=o.add,i&&o.add(function(){n=i},a[3-e][2].disable,a[3-e][3].disable,a[0][2].lock,a[0][3].lock),o.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=o.fireWith}),r.promise(s),t&&t.call(s,s),s},when:function(e){var t=arguments.length,a=t,n=Array(a),s=r.call(arguments),o=T.Deferred(),i=function(e){return function(a){n[e]=this,s[e]=arguments.length>1?r.call(arguments):a,--t||o.resolveWith(n,s)}};if(t<=1&&(R(e,o.done(i(a)).resolve,o.reject,!t),"pending"===o.state()||g(s[a]&&s[a].then)))return o.then();for(;a--;)R(s[a],i(a),o.reject);return o.promise()}});var q=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;T.Deferred.exceptionHook=function(t,a){e.console&&e.console.warn&&t&&q.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,a)},T.readyException=function(t){e.setTimeout(function(){throw t})};var N=T.Deferred();function F(){m.removeEventListener("DOMContentLoaded",F),e.removeEventListener("load",F),T.ready()}T.fn.ready=function(e){return N.then(e).catch(function(e){T.readyException(e)}),this},T.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--T.readyWait:T.isReady)||(T.isReady=!0,!0!==e&&--T.readyWait>0||N.resolveWith(m,[T]))}}),T.ready.then=N.then,"complete"===m.readyState||"loading"!==m.readyState&&!m.documentElement.doScroll?e.setTimeout(T.ready):(m.addEventListener("DOMContentLoaded",F),e.addEventListener("load",F));var U=function(e,t,a,n,r,s,o){var i=0,l=e.length,c=null==a;if("object"===v(a))for(i in r=!0,a)U(e,t,i,a[i],!0,s,o);else if(void 0!==n&&(r=!0,g(n)||(o=!0),c&&(o?(t.call(e,n),t=null):(c=t,t=function(e,t,a){return c.call(T(e),a)})),t))for(;i1,null,!0)},removeData:function(e){return this.each(function(){$.remove(this,e)})}}),T.extend({queue:function(e,t,a){var n;if(e)return t=(t||"fx")+"queue",n=Y.get(e,t),a&&(!n||Array.isArray(a)?n=Y.access(e,t,T.makeArray(a)):n.push(a)),n||[]},dequeue:function(e,t){t=t||"fx";var a=T.queue(e,t),n=a.length,r=a.shift(),s=T._queueHooks(e,t);"inprogress"===r&&(r=a.shift(),n--),r&&("fx"===t&&a.unshift("inprogress"),delete s.stop,r.call(e,function(){T.dequeue(e,t)},s)),!n&&s&&s.empty.fire()},_queueHooks:function(e,t){var a=t+"queueHooks";return Y.get(e,a)||Y.access(e,a,{empty:T.Callbacks("once memory").add(function(){Y.remove(e,[t+"queue",a])})})}}),T.fn.extend({queue:function(e,t){var a=2;return"string"!=typeof e&&(t=e,e="fx",a--),arguments.length\x20\t\r\n\f]*)/i,ge=/^$|^module$|\/(?:java|ecma)script/i;ue=m.createDocumentFragment().appendChild(m.createElement("div")),(pe=m.createElement("input")).setAttribute("type","radio"),pe.setAttribute("checked","checked"),pe.setAttribute("name","t"),ue.appendChild(pe),f.checkClone=ue.cloneNode(!0).cloneNode(!0).lastChild.checked,ue.innerHTML="",f.noCloneChecked=!!ue.cloneNode(!0).lastChild.defaultValue,ue.innerHTML="",f.option=!!ue.lastChild;var he={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function me(e,t){var a;return a=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&x(e,t)?T.merge([e],a):a}function ye(e,t){for(var a=0,n=e.length;a",""]);var ke=/<|&#?\w+;/;function ve(e,t,a,n,r){for(var s,o,i,l,c,u,p=t.createDocumentFragment(),d=[],f=0,g=e.length;f-1)r&&r.push(s);else if(c=ne(s),o=me(p.appendChild(s),"script"),c&&ye(o),a)for(u=0;s=o[u++];)ge.test(s.type||"")&&a.push(s);return p}var Te=/^key/,be=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,_e=/^([^.]*)(?:\.(.+)|)/;function we(){return!0}function Se(){return!1}function Ee(e,t){return e===function(){try{return m.activeElement}catch(e){}}()==("focus"===t)}function xe(e,t,a,n,r,s){var o,i;if("object"==typeof t){for(i in"string"!=typeof a&&(n=n||a,a=void 0),t)xe(e,i,a,n,t[i],s);return e}if(null==n&&null==r?(r=a,n=a=void 0):null==r&&("string"==typeof a?(r=n,n=void 0):(r=n,n=a,a=void 0)),!1===r)r=Se;else if(!r)return e;return 1===s&&(o=r,(r=function(e){return T().off(e),o.apply(this,arguments)}).guid=o.guid||(o.guid=T.guid++)),e.each(function(){T.event.add(this,t,r,n,a)})}function je(e,t,a){a?(Y.set(e,t,!1),T.event.add(e,t,{namespace:!1,handler:function(e){var n,s,o=Y.get(this,t);if(1&e.isTrigger&&this[t]){if(o.length)(T.event.special[t]||{}).delegateType&&e.stopPropagation();else if(o=r.call(arguments),Y.set(this,t,o),n=a(this,t),this[t](),o!==(s=Y.get(this,t))||n?Y.set(this,t,!1):s={},o!==s)return e.stopImmediatePropagation(),e.preventDefault(),s.value}else o.length&&(Y.set(this,t,{value:T.event.trigger(T.extend(o[0],T.Event.prototype),o.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,t)&&T.event.add(e,t,we)}T.event={global:{},add:function(e,t,a,n,r){var s,o,i,l,c,u,p,d,f,g,h,m=Y.get(e);if(K(e))for(a.handler&&(a=(s=a).handler,r=s.selector),r&&T.find.matchesSelector(ae,r),a.guid||(a.guid=T.guid++),(l=m.events)||(l=m.events=Object.create(null)),(o=m.handle)||(o=m.handle=function(t){return void 0!==T&&T.event.triggered!==t.type?T.event.dispatch.apply(e,arguments):void 0}),c=(t=(t||"").match(O)||[""]).length;c--;)f=h=(i=_e.exec(t[c])||[])[1],g=(i[2]||"").split(".").sort(),f&&(p=T.event.special[f]||{},f=(r?p.delegateType:p.bindType)||f,p=T.event.special[f]||{},u=T.extend({type:f,origType:h,data:n,handler:a,guid:a.guid,selector:r,needsContext:r&&T.expr.match.needsContext.test(r),namespace:g.join(".")},s),(d=l[f])||((d=l[f]=[]).delegateCount=0,p.setup&&!1!==p.setup.call(e,n,g,o)||e.addEventListener&&e.addEventListener(f,o)),p.add&&(p.add.call(e,u),u.handler.guid||(u.handler.guid=a.guid)),r?d.splice(d.delegateCount++,0,u):d.push(u),T.event.global[f]=!0)},remove:function(e,t,a,n,r){var s,o,i,l,c,u,p,d,f,g,h,m=Y.hasData(e)&&Y.get(e);if(m&&(l=m.events)){for(c=(t=(t||"").match(O)||[""]).length;c--;)if(f=h=(i=_e.exec(t[c])||[])[1],g=(i[2]||"").split(".").sort(),f){for(p=T.event.special[f]||{},d=l[f=(n?p.delegateType:p.bindType)||f]||[],i=i[2]&&new RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"),o=s=d.length;s--;)u=d[s],!r&&h!==u.origType||a&&a.guid!==u.guid||i&&!i.test(u.namespace)||n&&n!==u.selector&&("**"!==n||!u.selector)||(d.splice(s,1),u.selector&&d.delegateCount--,p.remove&&p.remove.call(e,u));o&&!d.length&&(p.teardown&&!1!==p.teardown.call(e,g,m.handle)||T.removeEvent(e,f,m.handle),delete l[f])}else for(f in l)T.event.remove(e,f+t[c],a,n,!0);T.isEmptyObject(l)&&Y.remove(e,"handle events")}},dispatch:function(e){var t,a,n,r,s,o,i=new Array(arguments.length),l=T.event.fix(e),c=(Y.get(this,"events")||Object.create(null))[l.type]||[],u=T.event.special[l.type]||{};for(i[0]=l,t=1;t=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==e.type||!0!==c.disabled)){for(s=[],o={},a=0;a-1:T.find(r,this,null,[c]).length),o[r]&&s.push(n);s.length&&i.push({elem:c,handlers:s})}return c=this,l\s*$/g;function Pe(e,t){return x(e,"table")&&x(11!==t.nodeType?t:t.firstChild,"tr")&&T(e).children("tbody")[0]||e}function Me(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function De(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var a,n,r,s,o,i;if(1===t.nodeType){if(Y.hasData(e)&&(i=Y.get(e).events))for(r in Y.remove(t,"handle events"),i)for(a=0,n=i[r].length;a1&&"string"==typeof m&&!f.checkClone&&Ae.test(m))return e.each(function(r){var s=e.eq(r);y&&(t[0]=m.call(this,r,s.html())),Ie(s,t,a,n)});if(d&&(o=(r=ve(t,e[0].ownerDocument,!1,e,n)).firstChild,1===r.childNodes.length&&(r=o),o||n)){for(l=(i=T.map(me(r,"script"),Me)).length;p0&&ye(o,!p&&me(e,"script")),u},cleanData:function(e){for(var t,a,n,r=T.event.special,s=0;void 0!==(a=e[s]);s++)if(K(a)){if(t=a[Y.expando]){if(t.events)for(n in t.events)r[n]?T.event.remove(a,n):T.removeEvent(a,n,t.handle);a[Y.expando]=void 0}a[$.expando]&&(a[$.expando]=void 0)}}}),T.fn.extend({detach:function(e){return Le(this,e,!0)},remove:function(e){return Le(this,e)},text:function(e){return U(this,function(e){return void 0===e?T.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Ie(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Pe(this,e).appendChild(e)})},prepend:function(){return Ie(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Pe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Ie(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(T.cleanData(me(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return T.clone(this,e,t)})},html:function(e){return U(this,function(e){var t=this[0]||{},a=0,n=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ce.test(e)&&!he[(fe.exec(e)||["",""])[1].toLowerCase()]){e=T.htmlPrefilter(e);try{for(;a3,ae.removeChild(t)),i}}))}();var Be=["Webkit","Moz","ms"],He=m.createElement("div").style,Ge={};function Ke(e){return T.cssProps[e]||Ge[e]||(e in He?e:Ge[e]=function(e){for(var t=e[0].toUpperCase()+e.slice(1),a=Be.length;a--;)if((e=Be[a]+t)in He)return e}(e)||e)}var We=/^(none|table(?!-c[ea]).+)/,Ye=/^--/,$e={position:"absolute",visibility:"hidden",display:"block"},Qe={letterSpacing:"0",fontWeight:"400"};function Xe(e,t,a){var n=ee.exec(t);return n?Math.max(0,n[2]-(a||0))+(n[3]||"px"):t}function Je(e,t,a,n,r,s){var o="width"===t?1:0,i=0,l=0;if(a===(n?"border":"content"))return 0;for(;o<4;o+=2)"margin"===a&&(l+=T.css(e,a+te[o],!0,r)),n?("content"===a&&(l-=T.css(e,"padding"+te[o],!0,r)),"margin"!==a&&(l-=T.css(e,"border"+te[o]+"Width",!0,r))):(l+=T.css(e,"padding"+te[o],!0,r),"padding"!==a?l+=T.css(e,"border"+te[o]+"Width",!0,r):i+=T.css(e,"border"+te[o]+"Width",!0,r));return!n&&s>=0&&(l+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-s-l-i-.5))||0),l}function Ze(e,t,a){var n=qe(e),r=(!f.boxSizingReliable()||a)&&"border-box"===T.css(e,"boxSizing",!1,n),s=r,o=Ue(e,t,n),i="offset"+t[0].toUpperCase()+t.slice(1);if(Re.test(o)){if(!a)return o;o="auto"}return(!f.boxSizingReliable()&&r||!f.reliableTrDimensions()&&x(e,"tr")||"auto"===o||!parseFloat(o)&&"inline"===T.css(e,"display",!1,n))&&e.getClientRects().length&&(r="border-box"===T.css(e,"boxSizing",!1,n),(s=i in e)&&(o=e[i])),(o=parseFloat(o)||0)+Je(e,t,a||(r?"border":"content"),s,n,o)+"px"}function et(e,t,a,n,r){return new et.prototype.init(e,t,a,n,r)}T.extend({cssHooks:{opacity:{get:function(e,t){if(t){var a=Ue(e,"opacity");return""===a?"1":a}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,a,n){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var r,s,o,i=G(t),l=Ye.test(t),c=e.style;if(l||(t=Ke(i)),o=T.cssHooks[t]||T.cssHooks[i],void 0===a)return o&&"get"in o&&void 0!==(r=o.get(e,!1,n))?r:c[t];"string"==(s=typeof a)&&(r=ee.exec(a))&&r[1]&&(a=oe(e,t,r),s="number"),null!=a&&a==a&&("number"!==s||l||(a+=r&&r[3]||(T.cssNumber[i]?"":"px")),f.clearCloneStyle||""!==a||0!==t.indexOf("background")||(c[t]="inherit"),o&&"set"in o&&void 0===(a=o.set(e,a,n))||(l?c.setProperty(t,a):c[t]=a))}},css:function(e,t,a,n){var r,s,o,i=G(t);return Ye.test(t)||(t=Ke(i)),(o=T.cssHooks[t]||T.cssHooks[i])&&"get"in o&&(r=o.get(e,!0,a)),void 0===r&&(r=Ue(e,t,n)),"normal"===r&&t in Qe&&(r=Qe[t]),""===a||a?(s=parseFloat(r),!0===a||isFinite(s)?s||0:r):r}}),T.each(["height","width"],function(e,t){T.cssHooks[t]={get:function(e,a,n){if(a)return!We.test(T.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,t,n):Ne(e,$e,function(){return Ze(e,t,n)})},set:function(e,a,n){var r,s=qe(e),o=!f.scrollboxSize()&&"absolute"===s.position,i=(o||n)&&"border-box"===T.css(e,"boxSizing",!1,s),l=n?Je(e,t,n,i,s):0;return i&&o&&(l-=Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-parseFloat(s[t])-Je(e,t,"border",!1,s)-.5)),l&&(r=ee.exec(a))&&"px"!==(r[3]||"px")&&(e.style[t]=a,a=T.css(e,t)),Xe(0,a,l)}}}),T.cssHooks.marginLeft=ze(f.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Ue(e,"marginLeft"))||e.getBoundingClientRect().left-Ne(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),T.each({margin:"",padding:"",border:"Width"},function(e,t){T.cssHooks[e+t]={expand:function(a){for(var n=0,r={},s="string"==typeof a?a.split(" "):[a];n<4;n++)r[e+te[n]+t]=s[n]||s[n-2]||s[0];return r}},"margin"!==e&&(T.cssHooks[e+t].set=Xe)}),T.fn.extend({css:function(e,t){return U(this,function(e,t,a){var n,r,s={},o=0;if(Array.isArray(t)){for(n=qe(e),r=t.length;o1)}}),T.Tween=et,et.prototype={constructor:et,init:function(e,t,a,n,r,s){this.elem=e,this.prop=a,this.easing=r||T.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=n,this.unit=s||(T.cssNumber[a]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,a=et.propHooks[this.prop];return this.options.duration?this.pos=t=T.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),a&&a.set?a.set(this):et.propHooks._default.set(this),this}},et.prototype.init.prototype=et.prototype,et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=T.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){T.fx.step[e.prop]?T.fx.step[e.prop](e):1!==e.elem.nodeType||!T.cssHooks[e.prop]&&null==e.elem.style[Ke(e.prop)]?e.elem[e.prop]=e.now:T.style(e.elem,e.prop,e.now+e.unit)}}},et.propHooks.scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},T.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},T.fx=et.prototype.init,T.fx.step={};var tt,at,nt=/^(?:toggle|show|hide)$/,rt=/queueHooks$/;function st(){at&&(!1===m.hidden&&e.requestAnimationFrame?e.requestAnimationFrame(st):e.setTimeout(st,T.fx.interval),T.fx.tick())}function ot(){return e.setTimeout(function(){tt=void 0}),tt=Date.now()}function it(e,t){var a,n=0,r={height:e};for(t=t?1:0;n<4;n+=2-t)r["margin"+(a=te[n])]=r["padding"+a]=e;return t&&(r.opacity=r.width=e),r}function lt(e,t,a){for(var n,r=(ct.tweeners[t]||[]).concat(ct.tweeners["*"]),s=0,o=r.length;s1)},removeAttr:function(e){return this.each(function(){T.removeAttr(this,e)})}}),T.extend({attr:function(e,t,a){var n,r,s=e.nodeType;if(3!==s&&8!==s&&2!==s)return void 0===e.getAttribute?T.prop(e,t,a):(1===s&&T.isXMLDoc(e)||(r=T.attrHooks[t.toLowerCase()]||(T.expr.match.bool.test(t)?ut:void 0)),void 0!==a?null===a?void T.removeAttr(e,t):r&&"set"in r&&void 0!==(n=r.set(e,a,t))?n:(e.setAttribute(t,a+""),a):r&&"get"in r&&null!==(n=r.get(e,t))?n:null==(n=T.find.attr(e,t))?void 0:n)},attrHooks:{type:{set:function(e,t){if(!f.radioValue&&"radio"===t&&x(e,"input")){var a=e.value;return e.setAttribute("type",t),a&&(e.value=a),t}}}},removeAttr:function(e,t){var a,n=0,r=t&&t.match(O);if(r&&1===e.nodeType)for(;a=r[n++];)e.removeAttribute(a)}}),ut={set:function(e,t,a){return!1===t?T.removeAttr(e,a):e.setAttribute(a,a),a}},T.each(T.expr.match.bool.source.match(/\w+/g),function(e,t){var a=pt[t]||T.find.attr;pt[t]=function(e,t,n){var r,s,o=t.toLowerCase();return n||(s=pt[o],pt[o]=r,r=null!=a(e,t,n)?o:null,pt[o]=s),r}});var dt=/^(?:input|select|textarea|button)$/i,ft=/^(?:a|area)$/i;function gt(e){return(e.match(O)||[]).join(" ")}function ht(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(O)||[]}T.fn.extend({prop:function(e,t){return U(this,T.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[T.propFix[e]||e]})}}),T.extend({prop:function(e,t,a){var n,r,s=e.nodeType;if(3!==s&&8!==s&&2!==s)return 1===s&&T.isXMLDoc(e)||(t=T.propFix[t]||t,r=T.propHooks[t]),void 0!==a?r&&"set"in r&&void 0!==(n=r.set(e,a,t))?n:e[t]=a:r&&"get"in r&&null!==(n=r.get(e,t))?n:e[t]},propHooks:{tabIndex:{get:function(e){var t=T.find.attr(e,"tabindex");return t?parseInt(t,10):dt.test(e.nodeName)||ft.test(e.nodeName)&&e.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),f.optSelected||(T.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),T.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){T.propFix[this.toLowerCase()]=this}),T.fn.extend({addClass:function(e){var t,a,n,r,s,o,i,l=0;if(g(e))return this.each(function(t){T(this).addClass(e.call(this,t,ht(this)))});if((t=mt(e)).length)for(;a=this[l++];)if(r=ht(a),n=1===a.nodeType&&" "+gt(r)+" "){for(o=0;s=t[o++];)n.indexOf(" "+s+" ")<0&&(n+=s+" ");r!==(i=gt(n))&&a.setAttribute("class",i)}return this},removeClass:function(e){var t,a,n,r,s,o,i,l=0;if(g(e))return this.each(function(t){T(this).removeClass(e.call(this,t,ht(this)))});if(!arguments.length)return this.attr("class","");if((t=mt(e)).length)for(;a=this[l++];)if(r=ht(a),n=1===a.nodeType&&" "+gt(r)+" "){for(o=0;s=t[o++];)for(;n.indexOf(" "+s+" ")>-1;)n=n.replace(" "+s+" "," ");r!==(i=gt(n))&&a.setAttribute("class",i)}return this},toggleClass:function(e,t){var a=typeof e,n="string"===a||Array.isArray(e);return"boolean"==typeof t&&n?t?this.addClass(e):this.removeClass(e):g(e)?this.each(function(a){T(this).toggleClass(e.call(this,a,ht(this),t),t)}):this.each(function(){var t,r,s,o;if(n)for(r=0,s=T(this),o=mt(e);t=o[r++];)s.hasClass(t)?s.removeClass(t):s.addClass(t);else void 0!==e&&"boolean"!==a||((t=ht(this))&&Y.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":Y.get(this,"__className__")||""))})},hasClass:function(e){var t,a,n=0;for(t=" "+e+" ";a=this[n++];)if(1===a.nodeType&&(" "+gt(ht(a))+" ").indexOf(t)>-1)return!0;return!1}});var yt=/\r/g;T.fn.extend({val:function(e){var t,a,n,r=this[0];return arguments.length?(n=g(e),this.each(function(a){var r;1===this.nodeType&&(null==(r=n?e.call(this,a,T(this).val()):e)?r="":"number"==typeof r?r+="":Array.isArray(r)&&(r=T.map(r,function(e){return null==e?"":e+""})),(t=T.valHooks[this.type]||T.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&void 0!==t.set(this,r,"value")||(this.value=r))})):r?(t=T.valHooks[r.type]||T.valHooks[r.nodeName.toLowerCase()])&&"get"in t&&void 0!==(a=t.get(r,"value"))?a:"string"==typeof(a=r.value)?a.replace(yt,""):null==a?"":a:void 0}}),T.extend({valHooks:{option:{get:function(e){var t=T.find.attr(e,"value");return null!=t?t:gt(T.text(e))}},select:{get:function(e){var t,a,n,r=e.options,s=e.selectedIndex,o="select-one"===e.type,i=o?null:[],l=o?s+1:r.length;for(n=s<0?l:o?s:0;n-1)&&(a=!0);return a||(e.selectedIndex=-1),s}}}}),T.each(["radio","checkbox"],function(){T.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=T.inArray(T(e).val(),t)>-1}},f.checkOn||(T.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),f.focusin="onfocusin"in e;var kt=/^(?:focusinfocus|focusoutblur)$/,vt=function(e){e.stopPropagation()};T.extend(T.event,{trigger:function(t,a,n,r){var s,o,i,l,c,p,d,f,y=[n||m],k=u.call(t,"type")?t.type:t,v=u.call(t,"namespace")?t.namespace.split("."):[];if(o=f=i=n=n||m,3!==n.nodeType&&8!==n.nodeType&&!kt.test(k+T.event.triggered)&&(k.indexOf(".")>-1&&(v=k.split("."),k=v.shift(),v.sort()),c=k.indexOf(":")<0&&"on"+k,(t=t[T.expando]?t:new T.Event(k,"object"==typeof t&&t)).isTrigger=r?2:3,t.namespace=v.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+v.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=n),a=null==a?[t]:T.makeArray(a,[t]),d=T.event.special[k]||{},r||!d.trigger||!1!==d.trigger.apply(n,a))){if(!r&&!d.noBubble&&!h(n)){for(l=d.delegateType||k,kt.test(l+k)||(o=o.parentNode);o;o=o.parentNode)y.push(o),i=o;i===(n.ownerDocument||m)&&y.push(i.defaultView||i.parentWindow||e)}for(s=0;(o=y[s++])&&!t.isPropagationStopped();)f=o,t.type=s>1?l:d.bindType||k,(p=(Y.get(o,"events")||Object.create(null))[t.type]&&Y.get(o,"handle"))&&p.apply(o,a),(p=c&&o[c])&&p.apply&&K(o)&&(t.result=p.apply(o,a),!1===t.result&&t.preventDefault());return t.type=k,r||t.isDefaultPrevented()||d._default&&!1!==d._default.apply(y.pop(),a)||!K(n)||c&&g(n[k])&&!h(n)&&((i=n[c])&&(n[c]=null),T.event.triggered=k,t.isPropagationStopped()&&f.addEventListener(k,vt),n[k](),t.isPropagationStopped()&&f.removeEventListener(k,vt),T.event.triggered=void 0,i&&(n[c]=i)),t.result}},simulate:function(e,t,a){var n=T.extend(new T.Event,a,{type:e,isSimulated:!0});T.event.trigger(n,null,t)}}),T.fn.extend({trigger:function(e,t){return this.each(function(){T.event.trigger(e,t,this)})},triggerHandler:function(e,t){var a=this[0];if(a)return T.event.trigger(e,t,a,!0)}}),f.focusin||T.each({focus:"focusin",blur:"focusout"},function(e,t){var a=function(e){T.event.simulate(t,e.target,T.event.fix(e))};T.event.special[t]={setup:function(){var n=this.ownerDocument||this.document||this,r=Y.access(n,t);r||n.addEventListener(e,a,!0),Y.access(n,t,(r||0)+1)},teardown:function(){var n=this.ownerDocument||this.document||this,r=Y.access(n,t)-1;r?Y.access(n,t,r):(n.removeEventListener(e,a,!0),Y.remove(n,t))}}});var Tt=e.location,bt={guid:Date.now()},_t=/\?/;T.parseXML=function(t){var a;if(!t||"string"!=typeof t)return null;try{a=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){a=void 0}return a&&!a.getElementsByTagName("parsererror").length||T.error("Invalid XML: "+t),a};var wt=/\[\]$/,St=/\r?\n/g,Et=/^(?:submit|button|image|reset|file)$/i,xt=/^(?:input|select|textarea|keygen)/i;function jt(e,t,a,n){var r;if(Array.isArray(t))T.each(t,function(t,r){a||wt.test(e)?n(e,r):jt(e+"["+("object"==typeof r&&null!=r?t:"")+"]",r,a,n)});else if(a||"object"!==v(t))n(e,t);else for(r in t)jt(e+"["+r+"]",t[r],a,n)}T.param=function(e,t){var a,n=[],r=function(e,t){var a=g(t)?t():t;n[n.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==a?"":a)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!T.isPlainObject(e))T.each(e,function(){r(this.name,this.value)});else for(a in e)jt(a,e[a],t,r);return n.join("&")},T.fn.extend({serialize:function(){return T.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=T.prop(this,"elements");return e?T.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!T(this).is(":disabled")&&xt.test(this.nodeName)&&!Et.test(e)&&(this.checked||!de.test(e))}).map(function(e,t){var a=T(this).val();return null==a?null:Array.isArray(a)?T.map(a,function(e){return{name:t.name,value:e.replace(St,"\r\n")}}):{name:t.name,value:a.replace(St,"\r\n")}}).get()}});var Ct=/%20/g,At=/#.*$/,Vt=/([?&])_=[^&]*/,Pt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Mt=/^(?:GET|HEAD)$/,Dt=/^\/\//,Ot={},It={},Lt="*/".concat("*"),Rt=m.createElement("a");function qt(e){return function(t,a){"string"!=typeof t&&(a=t,t="*");var n,r=0,s=t.toLowerCase().match(O)||[];if(g(a))for(;n=s[r++];)"+"===n[0]?(n=n.slice(1)||"*",(e[n]=e[n]||[]).unshift(a)):(e[n]=e[n]||[]).push(a)}}function Nt(e,t,a,n){var r={},s=e===It;function o(i){var l;return r[i]=!0,T.each(e[i]||[],function(e,i){var c=i(t,a,n);return"string"!=typeof c||s||r[c]?s?!(l=c):void 0:(t.dataTypes.unshift(c),o(c),!1)}),l}return o(t.dataTypes[0])||!r["*"]&&o("*")}function Ft(e,t){var a,n,r=T.ajaxSettings.flatOptions||{};for(a in t)void 0!==t[a]&&((r[a]?e:n||(n={}))[a]=t[a]);return n&&T.extend(!0,e,n),e}Rt.href=Tt.href,T.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Lt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":T.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Ft(Ft(e,T.ajaxSettings),t):Ft(T.ajaxSettings,e)},ajaxPrefilter:qt(Ot),ajaxTransport:qt(It),ajax:function(t,a){"object"==typeof t&&(a=t,t=void 0),a=a||{};var n,r,s,o,i,l,c,u,p,d,f=T.ajaxSetup({},a),g=f.context||f,h=f.context&&(g.nodeType||g.jquery)?T(g):T.event,y=T.Deferred(),k=T.Callbacks("once memory"),v=f.statusCode||{},b={},_={},w="canceled",S={readyState:0,getResponseHeader:function(e){var t;if(c){if(!o)for(o={};t=Pt.exec(s);)o[t[1].toLowerCase()+" "]=(o[t[1].toLowerCase()+" "]||[]).concat(t[2]);t=o[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return c?s:null},setRequestHeader:function(e,t){return null==c&&(e=_[e.toLowerCase()]=_[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==c&&(f.mimeType=e),this},statusCode:function(e){var t;if(e)if(c)S.always(e[S.status]);else for(t in e)v[t]=[v[t],e[t]];return this},abort:function(e){var t=e||w;return n&&n.abort(t),E(0,t),this}};if(y.promise(S),f.url=((t||f.url||Tt.href)+"").replace(Dt,Tt.protocol+"//"),f.type=a.method||a.type||f.method||f.type,f.dataTypes=(f.dataType||"*").toLowerCase().match(O)||[""],null==f.crossDomain){l=m.createElement("a");try{l.href=f.url,l.href=l.href,f.crossDomain=Rt.protocol+"//"+Rt.host!=l.protocol+"//"+l.host}catch(e){f.crossDomain=!0}}if(f.data&&f.processData&&"string"!=typeof f.data&&(f.data=T.param(f.data,f.traditional)),Nt(Ot,f,a,S),c)return S;for(p in(u=T.event&&f.global)&&0==T.active++&&T.event.trigger("ajaxStart"),f.type=f.type.toUpperCase(),f.hasContent=!Mt.test(f.type),r=f.url.replace(At,""),f.hasContent?f.data&&f.processData&&0===(f.contentType||"").indexOf("application/x-www-form-urlencoded")&&(f.data=f.data.replace(Ct,"+")):(d=f.url.slice(r.length),f.data&&(f.processData||"string"==typeof f.data)&&(r+=(_t.test(r)?"&":"?")+f.data,delete f.data),!1===f.cache&&(r=r.replace(Vt,"$1"),d=(_t.test(r)?"&":"?")+"_="+bt.guid+++d),f.url=r+d),f.ifModified&&(T.lastModified[r]&&S.setRequestHeader("If-Modified-Since",T.lastModified[r]),T.etag[r]&&S.setRequestHeader("If-None-Match",T.etag[r])),(f.data&&f.hasContent&&!1!==f.contentType||a.contentType)&&S.setRequestHeader("Content-Type",f.contentType),S.setRequestHeader("Accept",f.dataTypes[0]&&f.accepts[f.dataTypes[0]]?f.accepts[f.dataTypes[0]]+("*"!==f.dataTypes[0]?", "+Lt+"; q=0.01":""):f.accepts["*"]),f.headers)S.setRequestHeader(p,f.headers[p]);if(f.beforeSend&&(!1===f.beforeSend.call(g,S,f)||c))return S.abort();if(w="abort",k.add(f.complete),S.done(f.success),S.fail(f.error),n=Nt(It,f,a,S)){if(S.readyState=1,u&&h.trigger("ajaxSend",[S,f]),c)return S;f.async&&f.timeout>0&&(i=e.setTimeout(function(){S.abort("timeout")},f.timeout));try{c=!1,n.send(b,E)}catch(e){if(c)throw e;E(-1,e)}}else E(-1,"No Transport");function E(t,a,o,l){var p,d,m,b,_,w=a;c||(c=!0,i&&e.clearTimeout(i),n=void 0,s=l||"",S.readyState=t>0?4:0,p=t>=200&&t<300||304===t,o&&(b=function(e,t,a){for(var n,r,s,o,i=e.contents,l=e.dataTypes;"*"===l[0];)l.shift(),void 0===n&&(n=e.mimeType||t.getResponseHeader("Content-Type"));if(n)for(r in i)if(i[r]&&i[r].test(n)){l.unshift(r);break}if(l[0]in a)s=l[0];else{for(r in a){if(!l[0]||e.converters[r+" "+l[0]]){s=r;break}o||(o=r)}s=s||o}if(s)return s!==l[0]&&l.unshift(s),a[s]}(f,S,o)),!p&&T.inArray("script",f.dataTypes)>-1&&(f.converters["text script"]=function(){}),b=function(e,t,a,n){var r,s,o,i,l,c={},u=e.dataTypes.slice();if(u[1])for(o in e.converters)c[o.toLowerCase()]=e.converters[o];for(s=u.shift();s;)if(e.responseFields[s]&&(a[e.responseFields[s]]=t),!l&&n&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=s,s=u.shift())if("*"===s)s=l;else if("*"!==l&&l!==s){if(!(o=c[l+" "+s]||c["* "+s]))for(r in c)if((i=r.split(" "))[1]===s&&(o=c[l+" "+i[0]]||c["* "+i[0]])){!0===o?o=c[r]:!0!==c[r]&&(s=i[0],u.unshift(i[1]));break}if(!0!==o)if(o&&e.throws)t=o(t);else try{t=o(t)}catch(e){return{state:"parsererror",error:o?e:"No conversion from "+l+" to "+s}}}return{state:"success",data:t}}(f,b,S,p),p?(f.ifModified&&((_=S.getResponseHeader("Last-Modified"))&&(T.lastModified[r]=_),(_=S.getResponseHeader("etag"))&&(T.etag[r]=_)),204===t||"HEAD"===f.type?w="nocontent":304===t?w="notmodified":(w=b.state,d=b.data,p=!(m=b.error))):(m=w,!t&&w||(w="error",t<0&&(t=0))),S.status=t,S.statusText=(a||w)+"",p?y.resolveWith(g,[d,w,S]):y.rejectWith(g,[S,w,m]),S.statusCode(v),v=void 0,u&&h.trigger(p?"ajaxSuccess":"ajaxError",[S,f,p?d:m]),k.fireWith(g,[S,w]),u&&(h.trigger("ajaxComplete",[S,f]),--T.active||T.event.trigger("ajaxStop")))}return S},getJSON:function(e,t,a){return T.get(e,t,a,"json")},getScript:function(e,t){return T.get(e,void 0,t,"script")}}),T.each(["get","post"],function(e,t){T[t]=function(e,a,n,r){return g(a)&&(r=r||n,n=a,a=void 0),T.ajax(T.extend({url:e,type:t,dataType:r,data:a,success:n},T.isPlainObject(e)&&e))}}),T.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),T._evalUrl=function(e,t,a){return T.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){T.globalEval(e,t,a)}})},T.fn.extend({wrapAll:function(e){var t;return this[0]&&(g(e)&&(e=e.call(this[0])),t=T(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return g(e)?this.each(function(t){T(this).wrapInner(e.call(this,t))}):this.each(function(){var t=T(this),a=t.contents();a.length?a.wrapAll(e):t.append(e)})},wrap:function(e){var t=g(e);return this.each(function(a){T(this).wrapAll(t?e.call(this,a):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){T(this).replaceWith(this.childNodes)}),this}}),T.expr.pseudos.hidden=function(e){return!T.expr.pseudos.visible(e)},T.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},T.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Ut={0:200,1223:204},zt=T.ajaxSettings.xhr();f.cors=!!zt&&"withCredentials"in zt,f.ajax=zt=!!zt,T.ajaxTransport(function(t){var a,n;if(f.cors||zt&&!t.crossDomain)return{send:function(r,s){var o,i=t.xhr();if(i.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(o in t.xhrFields)i[o]=t.xhrFields[o];for(o in t.mimeType&&i.overrideMimeType&&i.overrideMimeType(t.mimeType),t.crossDomain||r["X-Requested-With"]||(r["X-Requested-With"]="XMLHttpRequest"),r)i.setRequestHeader(o,r[o]);a=function(e){return function(){a&&(a=n=i.onload=i.onerror=i.onabort=i.ontimeout=i.onreadystatechange=null,"abort"===e?i.abort():"error"===e?"number"!=typeof i.status?s(0,"error"):s(i.status,i.statusText):s(Ut[i.status]||i.status,i.statusText,"text"!==(i.responseType||"text")||"string"!=typeof i.responseText?{binary:i.response}:{text:i.responseText},i.getAllResponseHeaders()))}},i.onload=a(),n=i.onerror=i.ontimeout=a("error"),void 0!==i.onabort?i.onabort=n:i.onreadystatechange=function(){4===i.readyState&&e.setTimeout(function(){a&&n()})},a=a("abort");try{i.send(t.hasContent&&t.data||null)}catch(e){if(a)throw e}},abort:function(){a&&a()}}}),T.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),T.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return T.globalEval(e),e}}}),T.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),T.ajaxTransport("script",function(e){var t,a;if(e.crossDomain||e.scriptAttrs)return{send:function(n,r){t=T("