Skip to content

Commit

Permalink
Allow reset password to activate user if user activation enabled (#40)
Browse files Browse the repository at this point in the history
Since the reset password flow involves an email being sent to the user to confirm the password reset, this should satisfy user activation as well as the same requirement is met.

Refs: #35 (comment)
  • Loading branch information
bennothommo committed Jun 11, 2023
1 parent 1522c91 commit bf28200
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 22 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ jobs:

- name: Run unit tests (1.2/develop)
if: matrix.winterRelease != 'v1.1.9'
run: php artisan winter:test -p Winter.User
run: php artisan winter:test -p Winter.User -- --testdox

- name: Run unit tests (1.1)
if: matrix.winterRelease == 'v1.1.9'
working-directory: plugins/winter/user
run: ../../../vendor/bin/phpunit --bootstrap ../../../tests/bootstrap.php
run: ../../../vendor/bin/phpunit --bootstrap ../../../tests/bootstrap.php --testdox
33 changes: 33 additions & 0 deletions models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,31 @@ public function attemptActivation($code)
return true;
}

/**
* Attempts to reset a user's password by matching the reset code generated with the user's.
*
* If user activation is enabled, the user will be activated as well.
*
* @param string $resetCode
* @param string $newPassword
* @return bool
*/
public function attemptResetPassword($resetCode, $newPassword)
{
if (!parent::attemptResetPassword($resetCode, $newPassword)) {
return false;
}

if ($this->isActivatedByUser()) {
$this->activation_code = null;
$this->is_activated = true;
$this->activated_at = $this->freshTimestamp();
$this->forceSave();
}

return true;
}

/**
* Converts a guest user to a registered one and sends an invitation notification.
* @return void
Expand Down Expand Up @@ -541,4 +566,12 @@ public function canBeImpersonated($impersonator = false)

return true;
}

/**
* Determines if activation is done by the user.
*/
public function isActivatedByUser(): bool
{
return (UserSettings::get('activate_mode') === UserSettings::ACTIVATE_USER);
}
}
16 changes: 3 additions & 13 deletions tests/UserPluginTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,7 @@
use Illuminate\Foundation\AliasLoader;
use Winter\User\Models\Settings;

if (class_exists('System\Tests\Bootstrap\PluginTestCase')) {
class BaseTestCase extends \System\Tests\Bootstrap\PluginTestCase
{
}
} else {
class BaseTestCase extends \PluginTestCase
{
}
}

abstract class UserPluginTestCase extends BaseTestCase
abstract class UserPluginTestCase extends \PluginTestCase
{
/**
* @var array Plugins to refresh between tests.
Expand All @@ -41,9 +31,9 @@ public function setUp(): void
// register the auth facade
$alias = AliasLoader::getInstance();
$alias->alias('Auth', 'Winter\User\Facades\Auth');

App::singleton('user.auth', function () {
return \Winter\User\Classes\AuthManager::instance();
});
}
}
}
16 changes: 9 additions & 7 deletions tests/unit/facades/AuthFacadeTest.php
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
<?php namespace Winter\User\Tests\Unit\Facades;
<?php

namespace Winter\User\Tests\Unit\Facades;

use Auth;
use Winter\User\Models\User;
use Winter\User\Tests\UserPluginTestCase;

class AuthFacadeTest extends UserPluginTestCase
{
public function testRegisteringAUser()
public function testCanRegisterAUser()
{
// register a user
$user = Auth::register([
Expand All @@ -19,14 +21,14 @@ public function testRegisteringAUser()
// our one user should be returned
$this->assertEquals(1, User::count());
$this->assertInstanceOf('Winter\User\Models\User', $user);

// and that user should have the following data
$this->assertFalse($user->is_activated);
$this->assertEquals('Some User', $user->name);
$this->assertEquals('[email protected]', $user->email);
}

public function testRegisteringAUserWithAutoActivation()
public function testCanRegisterAndAutomaticallyActivateAUser()
{
// register a user with the auto-activate flag
$user = Auth::register([
Expand All @@ -43,7 +45,7 @@ public function testRegisteringAUserWithAutoActivation()
$this->assertTrue(Auth::check());
}

public function testRegisteringAGuest()
public function testCanRegisterAGuest()
{
// register a guest
$guest = Auth::registerGuest(['email' => '[email protected]']);
Expand All @@ -57,7 +59,7 @@ public function testRegisteringAGuest()
$this->assertEquals('[email protected]', $guest->email);
}

public function testLoginAndCheckingAuthentication()
public function testCanLoginAndCheckAuthenticationAndActivation()
{
// we should not be authenticated
$this->assertFalse(Auth::check());
Expand All @@ -81,4 +83,4 @@ public function testLoginAndCheckingAuthentication()
// we should now be authenticated
$this->assertTrue(Auth::check());
}
}
}
48 changes: 48 additions & 0 deletions tests/unit/models/UserModelTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Winter\User\Tests\Unit\Models;

use Mockery;
use Winter\User\Models\User;
use Winter\User\Tests\UserPluginTestCase;

class UserModelTest extends UserPluginTestCase
{
public function testCanActivateUserOnPasswordResetIfUserActivationEnabled()
{
$userMock = Mockery::mock(User::class)->makePartial();
$userMock->shouldReceive('isActivatedByUser')->andReturn(true);
$userMock->shouldReceive('flushEventListeners')->andReturnNull();

$userMock->fill([
'name' => 'Some User',
'email' => '[email protected]',
'password' => 'changeme',
]);
$userMock->reset_password_code = '12345abcde';
$userMock->save();

// Attempt a password reset
$this->assertTrue($userMock->attemptResetPassword('12345abcde', 'newpassword'));
$this->assertTrue($userMock->is_activated);
}

public function testWontActivateUserOnPasswordResetIfUserActivationNotEnabled()
{
$userMock = Mockery::mock(User::class)->makePartial();
$userMock->shouldReceive('isActivatedByUser')->andReturn(false);
$userMock->shouldReceive('flushEventListeners')->andReturnNull();

$userMock->fill([
'name' => 'Some User',
'email' => '[email protected]',
'password' => 'changeme',
]);
$userMock->reset_password_code = '12345abcde';
$userMock->save();

// Attempt a password reset
$this->assertTrue($userMock->attemptResetPassword('12345abcde', 'newpassword'));
$this->assertFalse($userMock->is_activated);
}
}

0 comments on commit bf28200

Please sign in to comment.