From 4db78fd56151c3b3a9efc121897666332af3f6b1 Mon Sep 17 00:00:00 2001 From: Poldovico <41841263+Poldovico@users.noreply.github.com> Date: Tue, 7 May 2019 15:21:00 +0200 Subject: [PATCH 01/24] Respects CSRF_ENABLED environment variable The previous statement would evaluate to true for any value of CSRF_ENABLED. Using the strict comparison operator means if we set the variable to any false-evaluating values other then boolean false (0, '0', 'false', '' and so on), then CSRF will be disabled. getenv() evaluates to boolean false if the environment variable is not set, so I know of no simple way to distinguish between the variable being unset, in which case we want to default to enabling CSRF, and it being explicitly set to boolean false. --- app/sprinkles/core/config/default.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index aec6d554e..17b5cda7e 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -96,7 +96,7 @@ * Note : CSRF Middleware should only be disabled for dev or debug purposes. */ 'csrf' => [ - 'enabled' => getenv('CSRF_ENABLED') ?: true, + 'enabled' => (getenv('CSRF_ENABLED') !== false) ? getenv('CSRF_ENABLED') : true, 'name' => 'csrf', 'storage_limit' => 200, 'strength' => 16, From ee3083b391dd161831cec0d3d68b0173e8a11ed5 Mon Sep 17 00:00:00 2001 From: Rob Thomas Date: Tue, 4 Jun 2019 10:40:50 +1000 Subject: [PATCH 02/24] Fixes UserFrosting Issue #990 This allows the domain to be configured in the uf4-rememberme cookie. --- app/sprinkles/account/src/Authenticate/Authenticator.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index 0ce3eb7ff..8eace3857 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -122,6 +122,11 @@ public function __construct(ClassMapper $classMapper, Session $session, Config $ $this->rememberMe->getCookie()->setExpireTime($this->config['remember_me.expire_time']); } + // Set domain, if specified + if ($this->config->has('remember_me.domain') && ($this->config->has('remember_me.domain') != null)) { + $this->rememberMe->getCookie()->setDomain($this->config['remember_me.domain']); + } + $this->user = null; $this->viaRemember = false; } From 6e1e316285218864dda20c84e95ffbf24fbfddb7 Mon Sep 17 00:00:00 2001 From: Rob Thomas Date: Fri, 7 Jun 2019 12:23:03 +1000 Subject: [PATCH 03/24] Add some documentation about remember me, and domain --- app/sprinkles/account/config/default.php | 26 +++++++++++++++++++ .../src/Authenticate/Authenticator.php | 4 +-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index 359dbdd05..bec27eee5 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -55,11 +55,37 @@ * RememberMe Package Settings * ---------------------------------------------------------------------- * See https://github.com/gbirke/rememberme for an explanation of these settings + * + * Note that the 'domain' field can be set to match your top-level-domain if you + * want to send the rememberme to all hosts in your domain. An automatic config + * of this can be done in your config.php with code similar to this: + * + * if (!empty($_SERVER['SERVER_NAME']) && filter_var($_SERVER['SERVER_NAME'], \FILTER_VALIDATE_IP) === false) { + * $darr = explode(".", $_SERVER['SERVER_NAME']); + * array_shift($darr); + * $conf['session']['cookie_parameters'] = [ "lifetime" => 86400, "domain" => ".".join(".", $darr), "path" => "/" ]; + * $conf['remember_me'] = [ "domain" => ".".join(".", $darr) ]; + * } + * + * (Or, for production, you can hard-code the domain rather than calculating it on each page load) + * + * This is DELIBERATELY NOT TURNED ON BY DEFAULT! + * + * If you enable the 'domain' (on both the session and the remember_me cookies) + * you will be sending your authentication cookies to every machine in the + * domain you are using. This may not be bad if you control the domain, but + * if you are using a VPS and the hostname of the machine you are connecting to + * is, for example, host2.vps.blah.com, and you connect to host20.vps.blah.com, + * your browser will send your (super secret) cookies to host20.vps.blah.com. + * + * You only want to turn this on if you want machine1.foo.com to receive the + * cookies that THIS MACHINE (machine2.foo.com) set. */ 'remember_me' => [ 'cookie' => [ 'name' => 'rememberme', ], + 'domain' => null, 'expire_time' => 604800, 'session' => [ 'path' => '/', diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index 8eace3857..4847a2a1b 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -118,12 +118,12 @@ public function __construct(ClassMapper $classMapper, Session $session, Config $ $this->rememberMe->getCookie()->setPath($this->config['remember_me.session.path']); // Set expire time, if specified - if ($this->config->has('remember_me.expire_time') && ($this->config->has('remember_me.expire_time') != null)) { + if ($this->config->has('remember_me.expire_time') && $this->config->has('remember_me.expire_time') != null) { $this->rememberMe->getCookie()->setExpireTime($this->config['remember_me.expire_time']); } // Set domain, if specified - if ($this->config->has('remember_me.domain') && ($this->config->has('remember_me.domain') != null)) { + if ($this->config->has('remember_me.domain') && $this->config->has('remember_me.domain') != null) { $this->rememberMe->getCookie()->setDomain($this->config['remember_me.domain']); } From 93019852e9948d95319657cf7bece0c54236c7c4 Mon Sep 17 00:00:00 2001 From: Rob Thomas Date: Fri, 7 Jun 2019 13:59:38 +1000 Subject: [PATCH 04/24] Sigh. --- app/sprinkles/account/config/default.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index bec27eee5..5bc43ed86 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -79,13 +79,13 @@ * your browser will send your (super secret) cookies to host20.vps.blah.com. * * You only want to turn this on if you want machine1.foo.com to receive the - * cookies that THIS MACHINE (machine2.foo.com) set. + * cookies that THIS MACHINE (machine2.foo.com) set. */ 'remember_me' => [ 'cookie' => [ 'name' => 'rememberme', ], - 'domain' => null, + 'domain' => null, 'expire_time' => 604800, 'session' => [ 'path' => '/', From d842249fe6ba198b40361dcb206d10a170d35e59 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 8 Jun 2019 09:37:41 -0400 Subject: [PATCH 05/24] Updated Changelog [ci skip] --- CHANGELOG.md | 6 ++++++ app/defines.php | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32e8f904c..5e6780621 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [v4.2.3] + +### Added +- Config to set Domain of RememberMe Cookie ([#990]; [#991]; Thanks @xrobau!) + + ## [v4.2.2] ### Added diff --git a/app/defines.php b/app/defines.php index eb94fa14c..468221b69 100755 --- a/app/defines.php +++ b/app/defines.php @@ -11,7 +11,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.2.2'); +define('UserFrosting\VERSION', '4.2.3-dev'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.2'); From 1b2f82837d27abad8a251ec842b2a7a6fb81152d Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 8 Jun 2019 09:43:03 -0400 Subject: [PATCH 06/24] Updated Changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e6780621..1202861d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -764,7 +764,10 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#968]: https://github.com/userfrosting/UserFrosting/issues/968 [#981]: https://github.com/userfrosting/UserFrosting/issues/981 [#983]: https://github.com/userfrosting/UserFrosting/issues/983 +[#990]: https://github.com/userfrosting/UserFrosting/issues/990 +[#991]: https://github.com/userfrosting/UserFrosting/issues/991 [v4.2.0]: https://github.com/userfrosting/UserFrosting/compare/v4.1.22...v4.2.0 [v4.2.1]: https://github.com/userfrosting/UserFrosting/compare/v4.2.0...v.4.2.1 [v4.2.2]: https://github.com/userfrosting/UserFrosting/compare/v.4.2.1...v4.2.2 +[v4.2.3]: https://github.com/userfrosting/UserFrosting/compare/v4.2.2...v4.2.3 From 61755e0a66d18f42feaa8dfea5078e2f72a862db Mon Sep 17 00:00:00 2001 From: Rob Thomas Date: Mon, 10 Jun 2019 08:39:11 +1000 Subject: [PATCH 07/24] Fixes UserFrosting#965 - Ignore files that don't end in .php This ignores any files in Migrations that do not end in .php. It causes problems when scripts, or data, or documentation is left in the Migrations directory, and the migration task assumes that they are PHP Classes and crashes. Signed-Off-By: Rob Thomas --- .../core/src/Database/Migrator/MigrationLocator.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php index 58f4ce6bb..3ee918af1 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -54,7 +54,11 @@ public function getMigrations() $migrations = []; foreach ($migrationFiles as $migrationFile) { - $migrations[] = $this->getMigrationDetails($migrationFile); + // Note that PSR4 insists that all php files must end in PHP, so ignore all + // files that don't end in PHP. + if (preg_match('/php$/', $migrationFile)) { + $migrations[] = $this->getMigrationDetails($migrationFile); + } } return $migrations; From e32313e640c8563f53d7aefe8182e7644e6457a2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 12 Jun 2019 21:11:11 -0400 Subject: [PATCH 08/24] Added test for PR #998 --- .../Integration/Database/Migrator/MigrationLocatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php index 44c842263..a5c0fbdcb 100644 --- a/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php @@ -90,6 +90,7 @@ public function testGetMigrations() new Resource($resourceStream, $resourceAccountLocation, 'one/CreatePasswordResetsTable.php'), new Resource($resourceStream, $resourceAccountLocation, 'two/CreateFlightsTable.php'), new Resource($resourceStream, $resourceAccountLocation, 'CreateMainTable.php'), + new Resource($resourceStream, $resourceAccountLocation, 'README.md'), // This shoudn't be returned by the migrator ]); // Create a new MigrationLocator instance with our simulated ResourceLocation @@ -109,7 +110,6 @@ public function testGetMigrations() ]; // Test results match expectations - $this->assertCount(8, $results); $this->assertEquals($expected, $results); return $locator; From 1044eef1327b0f8cf17ffa790410dd129f28d61c Mon Sep 17 00:00:00 2001 From: avsdev-cw Date: Thu, 13 Jun 2019 02:37:29 +0100 Subject: [PATCH 09/24] Config settings for password min/max length (#993) Created config settings for password min/max length and updated all references to use those values. --- app/sprinkles/account/config/default.php | 9 ++++- .../account/locale/es_ES/messages.php | 2 +- .../account/src/Bakery/CreateAdminUser.php | 13 ++++-- .../src/Controller/AccountController.php | 40 +++++++++++++++++-- .../forms/settings-account.html.twig | 2 +- .../templates/pages/register.html.twig | 2 +- .../templates/pages/reset-password.html.twig | 2 +- .../templates/pages/set-password.html.twig | 2 +- .../admin/src/Controller/RoleController.php | 2 + .../admin/src/Controller/UserController.php | 9 +++++ .../modals/user-set-password.html.twig | 2 +- 11 files changed, 71 insertions(+), 14 deletions(-) diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index 5bc43ed86..8c92c8f93 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -122,7 +122,8 @@ * Account Site Settings * ---------------------------------------------------------------------- * "Site" settings that are automatically passed to Twig. Use theses - * settings to control the login and registration process + * settings to control the login, password (re)set and registration + * processes */ 'site' => [ 'login' => [ @@ -141,6 +142,12 @@ ], ], ], + 'password' => [ + 'length' => [ + 'min' => 8, + 'max' => 25, + ], + ], ], /* diff --git a/app/sprinkles/account/locale/es_ES/messages.php b/app/sprinkles/account/locale/es_ES/messages.php index 3bcdf77a2..5e993f56e 100755 --- a/app/sprinkles/account/locale/es_ES/messages.php +++ b/app/sprinkles/account/locale/es_ES/messages.php @@ -99,7 +99,7 @@ 'PASSWORD' => [ '@TRANSLATION' => 'Contraseña', - 'BETWEEN' => 'Entre {{min}} - {{max}} (recomendado 12)', + 'BETWEEN' => 'Entre {{min}} - {{max}}', 'CONFIRM' => 'Confirmar contraseña', 'CONFIRM_CURRENT' => 'Por favor, confirma tu contraseña actual', diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index 3e77118ac..d3166e0f3 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -298,8 +298,11 @@ protected function validateLastName($lastName) */ protected function askPassword($password = '', $requireConfirmation = true) { + $passwordMin = $this->ci->config['site.password.length.min']; + $passwordMax = $this->ci->config['site.password.length.max']; + while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password, $requireConfirmation)) { - $password = $this->io->askHidden('Enter password (12-255 characters)'); + $password = $this->io->askHidden('Enter password (' . $passwordMin . '-' . $passwordMax . ' characters)'); } return $password; @@ -314,9 +317,11 @@ protected function askPassword($password = '', $requireConfirmation = true) */ protected function validatePassword($password) { - //TODO Config for this ?? - if (strlen($password) < 12 || strlen($password) > 255) { - $this->io->error('Password must be between 12-255 characters'); + $passwordMin = $this->ci->config['site.password.length.min']; + $passwordMax = $this->ci->config['site.password.length.max']; + + if (strlen($password) < $passwordMin || strlen($password) > $passwordMax) { + $this->io->error('Password must be between ' . $passwordMin . ' and ' . $passwordMax . ' characters'); return false; } diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index d184b773d..db82c1572 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -519,6 +519,10 @@ public function pageRegister(Request $request, Response $response, $args) // Load validation rules $schema = new RequestSchema('schema://requests/register.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator); // Get locale information @@ -593,11 +597,18 @@ public function pageResendVerification(Request $request, Response $response, $ar */ public function pageResetPassword(Request $request, Response $response, $args) { + /** @var \UserFrosting\Support\Repository\Repository $config */ + $config = $this->ci->config; + // Insert the user's secret token from the link into the password reset form $params = $request->getQueryParams(); // Load validation rules - note this uses the same schema as "set password" $schema = new RequestSchema('schema://requests/set-password.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); $validator = new JqueryValidationAdapter($schema, $this->ci->translator); return $this->ci->view->render($response, 'pages/reset-password.html.twig', [ @@ -627,11 +638,18 @@ public function pageResetPassword(Request $request, Response $response, $args) */ public function pageSetPassword(Request $request, Response $response, $args) { + /** @var \UserFrosting\Support\Repository\Repository $config */ + $config = $this->ci->config; + // Insert the user's secret token from the link into the password set form $params = $request->getQueryParams(); // Load validation rules $schema = new RequestSchema('schema://requests/set-password.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); $validator = new JqueryValidationAdapter($schema, $this->ci->translator); return $this->ci->view->render($response, 'pages/set-password.html.twig', [ @@ -664,6 +682,9 @@ public function pageSetPassword(Request $request, Response $response, $args) */ public function pageSettings(Request $request, Response $response, $args) { + /** @var \UserFrosting\Support\Repository\Repository $config */ + $config = $this->ci->config; + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; @@ -677,14 +698,15 @@ public function pageSettings(Request $request, Response $response, $args) // Load validation rules $schema = new RequestSchema('schema://requests/account-settings.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); $validatorAccountSettings = new JqueryValidationAdapter($schema, $this->ci->translator); $schema = new RequestSchema('schema://requests/profile-settings.yaml'); $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator); - /** @var \UserFrosting\Support\Repository\Repository $config */ - $config = $this->ci->config; - // Get a list of all locales $locales = $config->getDefined('site.locales.available'); @@ -919,6 +941,10 @@ public function register(Request $request, Response $response, $args) // Load the request schema $schema = new RequestSchema('schema://requests/register.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); // Whitelist and set parameter defaults $transformer = new RequestDataTransformer($schema); @@ -1117,6 +1143,10 @@ public function setPassword(Request $request, Response $response, $args) // Load the request schema $schema = new RequestSchema('schema://requests/set-password.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); // Whitelist and set parameter defaults $transformer = new RequestDataTransformer($schema); @@ -1210,6 +1240,10 @@ public function settings(Request $request, Response $response, $args) // Load the request schema $schema = new RequestSchema('schema://requests/account-settings.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); // Whitelist and set parameter defaults $transformer = new RequestDataTransformer($schema); diff --git a/app/sprinkles/account/templates/forms/settings-account.html.twig b/app/sprinkles/account/templates/forms/settings-account.html.twig index 996b27b57..357dca336 100644 --- a/app/sprinkles/account/templates/forms/settings-account.html.twig +++ b/app/sprinkles/account/templates/forms/settings-account.html.twig @@ -16,7 +16,7 @@ {% if page.visibility != "disabled" %}
- +
diff --git a/app/sprinkles/account/templates/pages/register.html.twig b/app/sprinkles/account/templates/pages/register.html.twig index a7f642b8e..06168643b 100644 --- a/app/sprinkles/account/templates/pages/register.html.twig +++ b/app/sprinkles/account/templates/pages/register.html.twig @@ -47,7 +47,7 @@
- +
diff --git a/app/sprinkles/account/templates/pages/reset-password.html.twig b/app/sprinkles/account/templates/pages/reset-password.html.twig index 8e3a24adc..3f555a40f 100644 --- a/app/sprinkles/account/templates/pages/reset-password.html.twig +++ b/app/sprinkles/account/templates/pages/reset-password.html.twig @@ -30,7 +30,7 @@
- +
diff --git a/app/sprinkles/account/templates/pages/set-password.html.twig b/app/sprinkles/account/templates/pages/set-password.html.twig index 3c4fe2bab..d6af1d251 100644 --- a/app/sprinkles/account/templates/pages/set-password.html.twig +++ b/app/sprinkles/account/templates/pages/set-password.html.twig @@ -30,7 +30,7 @@
- +
diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index fdf304e7b..032b995f0 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -957,6 +957,8 @@ public function updateField(Request $request, Response $response, $args) // Load the request schema $schema = new RequestSchema('schema://requests/role/edit-field.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); // Whitelist and set parameter defaults $transformer = new RequestDataTransformer($schema); diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index caf9caba3..f81d19e9d 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -765,6 +765,9 @@ public function getModalEditPassword(Request $request, Response $response, $args /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; + /** @var \UserFrosting\Support\Repository\Repository $config */ + $config = $this->ci->config; + // Access-controlled resource - check that currentUser has permission to edit "password" field for this user if (!$authorizer->checkAccess($currentUser, 'update_user_field', [ 'user' => $user, @@ -775,6 +778,10 @@ public function getModalEditPassword(Request $request, Response $response, $args // Load validation rules $schema = new RequestSchema('schema://requests/user/edit-password.yaml'); + $schema->set('value.validators.length.min', $config['site.password.length.min']); + $schema->set('value.validators.length.max', $config['site.password.length.max']); + $schema->set('passwordc.validators.length.min', $config['site.password.length.min']); + $schema->set('passwordc.validators.length.max', $config['site.password.length.max']); $validator = new JqueryValidationAdapter($schema, $this->ci->translator); return $this->ci->view->render($response, 'modals/user-set-password.html.twig', [ @@ -1307,6 +1314,8 @@ public function updateField(Request $request, Response $response, $args) // Load the request schema $schema = new RequestSchema('schema://requests/user/edit-field.yaml'); + $schema->set('password.validators.length.min', $config['site.password.length.min']); + $schema->set('password.validators.length.max', $config['site.password.length.max']); // Whitelist and set parameter defaults $transformer = new RequestDataTransformer($schema); diff --git a/app/sprinkles/admin/templates/modals/user-set-password.html.twig b/app/sprinkles/admin/templates/modals/user-set-password.html.twig index 922d4e268..8b8872217 100644 --- a/app/sprinkles/admin/templates/modals/user-set-password.html.twig +++ b/app/sprinkles/admin/templates/modals/user-set-password.html.twig @@ -32,7 +32,7 @@
- +
From bfcd6748013f17b972c68d1db0a07df70579abf7 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 12 Jun 2019 21:39:44 -0400 Subject: [PATCH 10/24] Removed unnecessary line --- app/sprinkles/core/src/Csrf/SlimCsrfProvider.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php b/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php index 850a079e7..c51cc3f84 100644 --- a/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php +++ b/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php @@ -46,7 +46,6 @@ public static function setupService(ContainerInterface $ci) $e->addUserMessage('CSRF_MISSING'); throw $e; - return $next($request, $response); }; return new Guard($ci->config['csrf.name'], $csrfStorage, $onFailure, $ci->config['csrf.storage_limit'], $ci->config['csrf.strength'], $ci->config['csrf.persistent_token']); From 4739a54ac2fdc27950ec56fa49ae40f71f7d80a0 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 12 Jun 2019 21:42:22 -0400 Subject: [PATCH 11/24] Updated Changelog [ci skip] --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1202861d4..fc7f04722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Config to set Domain of RememberMe Cookie ([#990]; [#991]; Thanks @xrobau!) - +- Config settings for password min/max length ([#993]) ## [v4.2.2] @@ -766,6 +766,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#983]: https://github.com/userfrosting/UserFrosting/issues/983 [#990]: https://github.com/userfrosting/UserFrosting/issues/990 [#991]: https://github.com/userfrosting/UserFrosting/issues/991 +[#993]: https://github.com/userfrosting/UserFrosting/issues/993 [v4.2.0]: https://github.com/userfrosting/UserFrosting/compare/v4.1.22...v4.2.0 [v4.2.1]: https://github.com/userfrosting/UserFrosting/compare/v4.2.0...v.4.2.1 From d1221b95ed2f764fed5e06e15ea309d6dc512e67 Mon Sep 17 00:00:00 2001 From: Rob Thomas Date: Thu, 13 Jun 2019 12:08:28 +1000 Subject: [PATCH 12/24] Resolves Issue #986 - Turn off opportunistic TLS when disabled. (#987) This ensures that when you have disabled 'secure' in your mail config no TLS attempts are ... attempted. --- app/sprinkles/core/config/default.php | 2 +- app/sprinkles/core/src/Mail/Mailer.php | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 1da67ffd6..b8ef2b815 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -211,7 +211,7 @@ 'host' => getenv('SMTP_HOST') ?: null, 'port' => 587, 'auth' => true, - 'secure' => 'tls', + 'secure' => 'tls', // Enable TLS encryption. Set to `tls`, `ssl` or `false` (to disabled) 'username' => getenv('SMTP_USER') ?: null, 'password' => getenv('SMTP_PASSWORD') ?: null, 'smtp_debug' => 4, diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php index deb60f0c2..1bd0702b3 100644 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -67,6 +67,13 @@ public function __construct($logger, $config = []) $this->phpMailer->Password = $config['password']; $this->phpMailer->SMTPDebug = $config['smtp_debug']; + // Disable opportunistic encryption if secure is unset. This is + // required if you have an incorrect or invalid SSL Certificate on + // your SMTP host, but the server offers STARTTLS. + if (!$config['secure']) { + $this->phpMailer->SMTPAutoTLS = false; + } + if (isset($config['smtp_options'])) { $this->phpMailer->SMTPOptions = $config['smtp_options']; } From 55302e30dec6e0116ac8abc0937bec3ec26a348c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 12 Jun 2019 22:10:45 -0400 Subject: [PATCH 13/24] Updated Changelog [ci skip] --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc7f04722..c1bd968eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Config to set Domain of RememberMe Cookie ([#990]; [#991]; Thanks @xrobau!) - Config settings for password min/max length ([#993]) +### Fixed +- [PHPMailer] Turn off opportunistic TLS when disabled ([#986]; [#987]) + ## [v4.2.2] ### Added @@ -764,6 +767,8 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#968]: https://github.com/userfrosting/UserFrosting/issues/968 [#981]: https://github.com/userfrosting/UserFrosting/issues/981 [#983]: https://github.com/userfrosting/UserFrosting/issues/983 +[#986]: https://github.com/userfrosting/UserFrosting/issues/986 +[#987]: https://github.com/userfrosting/UserFrosting/issues/987 [#990]: https://github.com/userfrosting/UserFrosting/issues/990 [#991]: https://github.com/userfrosting/UserFrosting/issues/991 [#993]: https://github.com/userfrosting/UserFrosting/issues/993 From 72fe1c0d54d35fa99263b1360c0a7621a259ded9 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 12 Jun 2019 22:18:03 -0400 Subject: [PATCH 14/24] Updated Changelog [ci skip] --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1bd968eb..7e4bdad37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Fixed - [PHPMailer] Turn off opportunistic TLS when disabled ([#986]; [#987]) +- Migrator now ignore files that don't end in `.php` ([#965]; Temporary fix for [#998]) ## [v4.2.2] @@ -764,6 +765,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#953]: https://github.com/userfrosting/UserFrosting/issues/953 [#958]: https://github.com/userfrosting/UserFrosting/issues/958 [#963]: https://github.com/userfrosting/UserFrosting/issues/963 +[#965]: https://github.com/userfrosting/UserFrosting/issues/965 [#968]: https://github.com/userfrosting/UserFrosting/issues/968 [#981]: https://github.com/userfrosting/UserFrosting/issues/981 [#983]: https://github.com/userfrosting/UserFrosting/issues/983 @@ -772,6 +774,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#990]: https://github.com/userfrosting/UserFrosting/issues/990 [#991]: https://github.com/userfrosting/UserFrosting/issues/991 [#993]: https://github.com/userfrosting/UserFrosting/issues/993 +[#998]: https://github.com/userfrosting/UserFrosting/issues/998 [v4.2.0]: https://github.com/userfrosting/UserFrosting/compare/v4.1.22...v4.2.0 [v4.2.1]: https://github.com/userfrosting/UserFrosting/compare/v4.2.0...v.4.2.1 From e0f5d1b1591f67b08ac1547d6d6a6d69f1cc1395 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 15 Jun 2019 16:04:09 -0400 Subject: [PATCH 15/24] Fix migration PHP file detection --- .../core/src/Database/Migrator/MigrationLocator.php | 2 +- .../Database/Migrator/MigrationLocatorTest.php | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php index 3ee918af1..7059be976 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -56,7 +56,7 @@ public function getMigrations() foreach ($migrationFiles as $migrationFile) { // Note that PSR4 insists that all php files must end in PHP, so ignore all // files that don't end in PHP. - if (preg_match('/php$/', $migrationFile)) { + if ($migrationFile->getExtension() == 'php') { $migrations[] = $this->getMigrationDetails($migrationFile); } } diff --git a/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php index a5c0fbdcb..dbb94f16c 100644 --- a/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/Database/Migrator/MigrationLocatorTest.php @@ -90,7 +90,13 @@ public function testGetMigrations() new Resource($resourceStream, $resourceAccountLocation, 'one/CreatePasswordResetsTable.php'), new Resource($resourceStream, $resourceAccountLocation, 'two/CreateFlightsTable.php'), new Resource($resourceStream, $resourceAccountLocation, 'CreateMainTable.php'), - new Resource($resourceStream, $resourceAccountLocation, 'README.md'), // This shoudn't be returned by the migrator + + // Theses shoudn't be returned by the migrator + new Resource($resourceStream, $resourceAccountLocation, 'README.md'), + new Resource($resourceStream, $resourceAccountLocation, 'php.md'), + new Resource($resourceStream, $resourceAccountLocation, 'foo.foophp'), + new Resource($resourceStream, $resourceAccountLocation, 'blah.phpphp'), + new Resource($resourceStream, $resourceAccountLocation, 'bar.phpbar'), ]); // Create a new MigrationLocator instance with our simulated ResourceLocation From c3ab9a6f8529b07e25359bd299c4b837eb4b6f04 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 26 Jun 2019 21:40:24 -0400 Subject: [PATCH 16/24] Updated changelog [ci skip] --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e4bdad37..6aeb858d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [v4.2.3] ### Added -- Config to set Domain of RememberMe Cookie ([#990]; [#991]; Thanks @xrobau!) +- Config to set Domain of RememberMe Cookie ([#990], [#991]; Thanks @xrobau !) - Config settings for password min/max length ([#993]) ### Fixed -- [PHPMailer] Turn off opportunistic TLS when disabled ([#986]; [#987]) -- Migrator now ignore files that don't end in `.php` ([#965]; Temporary fix for [#998]) +- [PHPMailer] Turn off opportunistic TLS when disabled ([#986], [#987]) +- Migrator now ignore files that don't end in `.php` ([#965], [#998]) +- Respects CSRF_ENABLED environment variable ([#976]; Thanks @Poldovico !) ## [v4.2.2] @@ -767,6 +768,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#963]: https://github.com/userfrosting/UserFrosting/issues/963 [#965]: https://github.com/userfrosting/UserFrosting/issues/965 [#968]: https://github.com/userfrosting/UserFrosting/issues/968 +[#976]: https://github.com/userfrosting/UserFrosting/issues/976 [#981]: https://github.com/userfrosting/UserFrosting/issues/981 [#983]: https://github.com/userfrosting/UserFrosting/issues/983 [#986]: https://github.com/userfrosting/UserFrosting/issues/986 From 9ffe94c123a18cb741e6a5cdf85616c076fb2008 Mon Sep 17 00:00:00 2001 From: Amos Folz Date: Tue, 2 Jul 2019 03:01:39 +0000 Subject: [PATCH 17/24] Initial commit for MigrateCleanCommand --- .../core/src/Bakery/MigrateCleanCommand.php | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 app/sprinkles/core/src/Bakery/MigrateCleanCommand.php diff --git a/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php b/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php new file mode 100644 index 000000000..6173c711f --- /dev/null +++ b/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php @@ -0,0 +1,101 @@ +setName('migrate:clean') + ->setDescription('Clean stale records from migrations database') + ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') + ->addOption('migration', 'm', InputOption::VALUE_REQUIRED, 'The specific migration to rollback.') + ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of batch to rollback.', 1); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title('Migration clean'); + + // Get migrator + $migrator = $this->ci->migrator; + + // Set connection to the selected database + $migrator->setConnection($input->getOption('database')); + + // Get ran migrations. If repository doesn't exist, there's no ran + if (!$migrator->repositoryExists()) { + $ran = collect(); + } else { + $ran = $migrator->getRepository()->getMigrations(); + } + + // Get available migrations + $available = $migrator->getAvailableMigrations(); + + $stale = $this->getStaleRecords($ran, $available); + // print_r($stale); + + $this->cleanStaleRecords($stale, $migrator); + + // Display ran migrations + $this->io->section('Cleaned migrations'); + if ($ran->count() > 0) { + } else { + $this->io->note('No installed migrations'); + } + } + + protected function cleanStaleRecords(array $stale, $migrator) + { + // print_r($stale); + foreach ($stale as $staleFile) { + print_r($staleFile); + print_r($staleFile['migration']); + $migrator->$repository->delete($staleFile['migration']); + } + } + + /** + * Return an array of stale migrations. + * A migration is stale if not found in the available stack (class is not in the Filesystem). + * + * @param Collection $ran The ran migrations + * @param array $available The available migrations + * + * @return Collection Collection of stale migration classes. + */ + protected function getStaleRecords(Collection $ran, array $available) + { + return $filtered = collect($ran)->filter(function ($migration) use ($available) { + return !in_array($migration->migration, $available); + })->toArray(); + } +} From e24d370b673ebe41445fbecc5baa822630639f87 Mon Sep 17 00:00:00 2001 From: amosfolz <33728190+amosfolz@users.noreply.github.com> Date: Tue, 2 Jul 2019 18:55:06 -0400 Subject: [PATCH 18/24] Finished draft of MigrateCleanCommand.php Also updated messages in Migrator classes that command can be run to remove stale migrations. --- .../core/src/Bakery/MigrateCleanCommand.php | 53 +++++++++++-------- .../Migrator/MigrationDependencyAnalyser.php | 2 +- .../core/src/Database/Migrator/Migrator.php | 2 +- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php b/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php index 6173c711f..2b48e194d 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php @@ -14,12 +14,13 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; /** - * migrate:rollback Bakery Command - * Rollback the last migrations ran against the database. + * migrate:clean Bakery Command + * Remove stale migrations from the database. * - * @author Louis Charette + * @author Amos Folz */ class MigrateCleanCommand extends MigrateCommand { @@ -29,12 +30,8 @@ class MigrateCleanCommand extends MigrateCommand protected function configure() { $this->setName('migrate:clean') - ->setDescription('Clean stale records from migrations database') - ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') - ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') - ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') - ->addOption('migration', 'm', InputOption::VALUE_REQUIRED, 'The specific migration to rollback.') - ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of batch to rollback.', 1); + ->setDescription('Remove stale migrations from the database.') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.'); } /** @@ -61,26 +58,36 @@ protected function execute(InputInterface $input, OutputInterface $output) $available = $migrator->getAvailableMigrations(); $stale = $this->getStaleRecords($ran, $available); - // print_r($stale); - $this->cleanStaleRecords($stale, $migrator); + if ($stale->count() > 0) { + $this->io->section('Stale migrations'); + $this->io->listing($stale->toArray()); - // Display ran migrations - $this->io->section('Cleaned migrations'); - if ($ran->count() > 0) { + if (!$this->io->confirm('Continue and remove stale migrations?', false)) { + exit; + } + $this->io->section('Cleaned migrations'); + $this->cleanStaleRecords($stale, $migrator); + $this->io->listing($stale->toArray()); } else { - $this->io->note('No installed migrations'); + $this->io->note('No stale migrations'); } } - protected function cleanStaleRecords(array $stale, $migrator) + /** + * Delete stale migrations from the database. + * + * @param Collection $stale Collection of stale migartion classes. + * @param Migrator $migrator Migrator object + */ + protected function cleanStaleRecords(Collection $stale, Migrator $migrator) { - // print_r($stale); - foreach ($stale as $staleFile) { - print_r($staleFile); - print_r($staleFile['migration']); - $migrator->$repository->delete($staleFile['migration']); - } + $migrationRepository = $migrator->getRepository(); + + //Delete the stale migration classes from the database. + $stale->each(function ($class) use ($migrationRepository) { + $migrationRepository->delete($class); + }); } /** @@ -96,6 +103,6 @@ protected function getStaleRecords(Collection $ran, array $available) { return $filtered = collect($ran)->filter(function ($migration) use ($available) { return !in_array($migration->migration, $available); - })->toArray(); + })->pluck('migration'); } } diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index fa8a9a1ed..a8c02403a 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -210,7 +210,7 @@ protected function getMigrationDependencies($migration) // Make sure class exists if (!class_exists($migration)) { - throw new BadClassNameException("Unable to find the migration class '$migration'."); + throw new BadClassNameException("Unable to find the migration class '$migration'. Run 'php bakery migrate:clean' to remove stale migrations."); } // If the `dependencies` property exist and is static, use this one. diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index ccfc6b0b7..2511dab6a 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -453,7 +453,7 @@ protected function getQueries(MigrationInterface $migration, $method) public function resolve($migrationClassName) { if (!class_exists($migrationClassName)) { - throw new BadClassNameException("Unable to find the migration class '$migrationClassName'."); + throw new BadClassNameException("Unable to find the migration class '$migrationClassName'. Run 'php bakery migrate:clean' to remove stale migrations."); } $migration = new $migrationClassName($this->getSchemaBuilder()); From 68d3cc6d5a6ebaf329e6838bc418ba4a49023391 Mon Sep 17 00:00:00 2001 From: amosfolz <33728190+amosfolz@users.noreply.github.com> Date: Thu, 4 Jul 2019 10:07:16 -0400 Subject: [PATCH 19/24] Update MigrateCleanCommand.php Add help, add -f option to bypass confirmation prompt --- .../core/src/Bakery/MigrateCleanCommand.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php b/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php index 2b48e194d..13b371612 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCleanCommand.php @@ -31,7 +31,9 @@ protected function configure() { $this->setName('migrate:clean') ->setDescription('Remove stale migrations from the database.') - ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.'); + ->setHelp('Removes stale migrations, which are simply migration class files that have been removed from the Filesystem. E.g. if you run a migration and then delete the migration class file prior to running `down()` for that migration it becomes stale. If a migration is a dependency of another migration you probably want to try to restore the files instead of running this command to avoid further issues.') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Do not prompt for confirmation.'); } /** @@ -60,11 +62,13 @@ protected function execute(InputInterface $input, OutputInterface $output) $stale = $this->getStaleRecords($ran, $available); if ($stale->count() > 0) { - $this->io->section('Stale migrations'); - $this->io->listing($stale->toArray()); + if (!$input->getOption('force')) { + $this->io->section('Stale migrations'); + $this->io->listing($stale->toArray()); - if (!$this->io->confirm('Continue and remove stale migrations?', false)) { - exit; + if (!$this->io->confirm('Continue and remove stale migrations?', false)) { + exit; + } } $this->io->section('Cleaned migrations'); $this->cleanStaleRecords($stale, $migrator); From 811716addf0c4f82b8cd930235dc8fb6bda9e714 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 6 Jul 2019 10:35:18 -0400 Subject: [PATCH 20/24] Update changelog [ci skip] --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aeb858d3..05b5ca2ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - [PHPMailer] Turn off opportunistic TLS when disabled ([#986], [#987]) - Migrator now ignore files that don't end in `.php` ([#965], [#998]) - Respects CSRF_ENABLED environment variable ([#976]; Thanks @Poldovico !) +- Checkbox bug on password change form ([#1008]) +- On role page, users table action buttons not working ([#1010]) ## [v4.2.2] @@ -777,6 +779,8 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#991]: https://github.com/userfrosting/UserFrosting/issues/991 [#993]: https://github.com/userfrosting/UserFrosting/issues/993 [#998]: https://github.com/userfrosting/UserFrosting/issues/998 +[#1008]: https://github.com/userfrosting/UserFrosting/issues/1008 +[#1010]: https://github.com/userfrosting/UserFrosting/issues/1010 [v4.2.0]: https://github.com/userfrosting/UserFrosting/compare/v4.1.22...v4.2.0 [v4.2.1]: https://github.com/userfrosting/UserFrosting/compare/v4.2.0...v.4.2.1 From aa4e0bb5bd4a9ed9c50ead4ef22902db1ae2c066 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 6 Jul 2019 10:52:04 -0400 Subject: [PATCH 21/24] Update Travis setup --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5e72d174a..3855003c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,8 @@ services: - mysql - postgresql - memcached - - redis-server + # Temporary disabled as it's not compatible with PHP 5.6 + # - redis-server php: - 5.6 From 21e43dbfeabd43ffa0b65babc933806c8bfa404c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 6 Jul 2019 10:57:09 -0400 Subject: [PATCH 22/24] Update travis setup --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3855003c0..be1b1b4a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,7 @@ services: - mysql - postgresql - memcached - # Temporary disabled as it's not compatible with PHP 5.6 - # - redis-server + - redis-server php: - 5.6 @@ -36,7 +35,8 @@ before_install: - nvm install 10.12.0 # Install Redis and Memcached - echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - - printf "\n" | pecl install -f redis + # Temporary disabled as it's not compatible with PHP 5.6 + # - printf "\n" | pecl install -f redis before_script: # install deps and UF From 29fc8685fc7d97d8068d5a1c3e6a924f9e5696ab Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 6 Jul 2019 16:27:21 -0400 Subject: [PATCH 23/24] Update changelog [ci skip] --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05b5ca2ff..26960cffb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Config to set Domain of RememberMe Cookie ([#990], [#991]; Thanks @xrobau !) - Config settings for password min/max length ([#993]) +- `migrate:clean` bakery command ([#1007]) ### Fixed - [PHPMailer] Turn off opportunistic TLS when disabled ([#986], [#987]) @@ -779,6 +780,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#991]: https://github.com/userfrosting/UserFrosting/issues/991 [#993]: https://github.com/userfrosting/UserFrosting/issues/993 [#998]: https://github.com/userfrosting/UserFrosting/issues/998 +[#1007]: https://github.com/userfrosting/UserFrosting/issues/1007 [#1008]: https://github.com/userfrosting/UserFrosting/issues/1008 [#1010]: https://github.com/userfrosting/UserFrosting/issues/1010 From 77dfd35846dac4daf2332928ccd31bda0aa33920 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 6 Jul 2019 16:27:34 -0400 Subject: [PATCH 24/24] Prep 4.2.3 release --- app/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/defines.php b/app/defines.php index 468221b69..db20c35bd 100755 --- a/app/defines.php +++ b/app/defines.php @@ -11,7 +11,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.2.3-dev'); +define('UserFrosting\VERSION', '4.2.3'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.2');