diff --git a/config/users.php b/config/users.php
index 9348e77d55..40c26972e8 100644
--- a/config/users.php
+++ b/config/users.php
@@ -62,4 +62,20 @@
//
],
+ /*
+ |--------------------------------------------------------------------------
+ | Password Brokers
+ |--------------------------------------------------------------------------
+ |
+ | When resetting passwords, Statamic uses an appropriate password broker.
+ | Here you may define which broker should be used for each situation.
+ | You may want a longer expiry for user activations, for example.
+ |
+ */
+
+ 'passwords' => [
+ 'resets' => config('auth.defaults.passwords'),
+ 'activations' => config('auth.defaults.passwords'),
+ ],
+
];
diff --git a/resources/views/auth/passwords/reset.blade.php b/resources/views/auth/passwords/reset.blade.php
index df7641f20a..8aba9ba317 100644
--- a/resources/views/auth/passwords/reset.blade.php
+++ b/resources/views/auth/passwords/reset.blade.php
@@ -3,11 +3,11 @@
@section('content')
-
{{ __('Reset Password') }}
+ {{ $title }}
-
-
+
diff --git a/routes/web.php b/routes/web.php
index 9925d5cc7f..b18cb266cb 100755
--- a/routes/web.php
+++ b/routes/web.php
@@ -29,6 +29,9 @@
Route::post('password/email', 'ForgotPasswordController@sendResetLinkEmail')->name('password.email');
Route::get('password/reset/{token}', 'ResetPasswordController@showResetForm')->name('password.reset');
Route::post('password/reset', 'ResetPasswordController@reset')->name('password.reset.action');
+
+ Route::get('activate/{token}', 'ActivateAccountController@showResetForm')->name('account.activate');
+ Route::post('activate', 'ActivateAccountController@reset')->name('account.activate.action');
});
Statamic::additionalActionRoutes();
diff --git a/src/Actions/SendPasswordReset.php b/src/Actions/SendPasswordReset.php
index 74414d234c..8a5a1c3700 100644
--- a/src/Actions/SendPasswordReset.php
+++ b/src/Actions/SendPasswordReset.php
@@ -35,6 +35,10 @@ public function buttonText()
public function run($users, $values)
{
- $users->each->generateTokenAndSendPasswordResetNotification();
+ $users->each(function ($user) {
+ $user->password()
+ ? $user->generateTokenAndSendPasswordResetNotification()
+ : $user->generateTokenAndSendActivateAccountNotification();
+ });
}
}
diff --git a/src/Auth/Passwords/PasswordBrokerManager.php b/src/Auth/Passwords/PasswordBrokerManager.php
index 0c74c8fb39..3e70c7cd14 100644
--- a/src/Auth/Passwords/PasswordBrokerManager.php
+++ b/src/Auth/Passwords/PasswordBrokerManager.php
@@ -18,6 +18,7 @@ protected function createTokenRepository(array $config)
return new TokenRepository(
$this->app['files'],
$this->app['hash'],
+ $config['table'],
$key,
$config['expire'],
$config['throttle'] ?? 0
diff --git a/src/Auth/Passwords/PasswordReset.php b/src/Auth/Passwords/PasswordReset.php
index 7270065dc0..6424a59e23 100644
--- a/src/Auth/Passwords/PasswordReset.php
+++ b/src/Auth/Passwords/PasswordReset.php
@@ -4,14 +4,21 @@
class PasswordReset
{
+ const BROKER_RESETS = 'resets';
+ const BROKER_ACTIVATIONS = 'activations';
+
protected static $url;
protected static $redirect;
- public static function url($token)
+ public static function url($token, $broker)
{
+ $route = $broker === self::BROKER_ACTIVATIONS ? 'statamic.account.activate' : 'statamic.password.reset';
+
+ $defaultUrl = route($route, $token);
+
$url = static::$url
? sprintf('%s?token=%s', static::$url, $token)
- : route('statamic.password.reset', $token);
+ : $defaultUrl;
parse_str(parse_url($url, PHP_URL_QUERY) ?: '', $query);
diff --git a/src/Auth/Passwords/TokenRepository.php b/src/Auth/Passwords/TokenRepository.php
index 95d281fa23..9b226c8b5f 100644
--- a/src/Auth/Passwords/TokenRepository.php
+++ b/src/Auth/Passwords/TokenRepository.php
@@ -17,7 +17,7 @@ class TokenRepository extends DatabaseTokenRepository
protected $expires;
protected $path;
- public function __construct(Filesystem $files, HasherContract $hasher, $hashKey, $expires = 60, $throttle = 60)
+ public function __construct(Filesystem $files, HasherContract $hasher, $table, $hashKey, $expires = 60, $throttle = 60)
{
$this->files = $files;
$this->hasher = $hasher;
@@ -25,7 +25,7 @@ public function __construct(Filesystem $files, HasherContract $hasher, $hashKey,
$this->expires = $expires * 60;
$this->throttle = $throttle;
- $this->path = storage_path('statamic/password_resets.yaml');
+ $this->path = storage_path("statamic/password_resets/$table.yaml");
}
public function create(CanResetPasswordContract $user)
@@ -92,6 +92,10 @@ protected function getResets()
protected function putResets($resets)
{
+ if (! $this->files->isDirectory($dir = dirname($this->path))) {
+ $this->files->makeDirectory($dir);
+ }
+
$this->files->put($this->path, YAML::dump($resets->all()));
}
}
diff --git a/src/Auth/User.php b/src/Auth/User.php
index f516b30938..6036abb8e5 100644
--- a/src/Auth/User.php
+++ b/src/Auth/User.php
@@ -182,11 +182,12 @@ public function routeNotificationForMail($notification = null)
public function sendPasswordResetNotification($token)
{
- $notification = $this->password()
- ? new PasswordResetNotification($token)
- : new ActivateAccountNotification($token);
+ $this->notify(new PasswordResetNotification($token));
+ }
- $this->notify($notification);
+ public function sendActivateAccountNotification($token)
+ {
+ $this->notify(new ActivateAccountNotification($token));
}
public function generateTokenAndSendPasswordResetNotification()
@@ -194,14 +195,23 @@ public function generateTokenAndSendPasswordResetNotification()
$this->sendPasswordResetNotification($this->generatePasswordResetToken());
}
- public function getPasswordResetUrl()
+ public function generateTokenAndSendActivateAccountNotification()
{
- return PasswordReset::url($this->generatePasswordResetToken());
+ $this->sendActivateAccountNotification($this->generateActivateAccountToken());
}
public function generatePasswordResetToken()
{
- return Password::broker()->createToken($this);
+ $broker = config('statamic.users.passwords.'.PasswordReset::BROKER_RESETS);
+
+ return Password::broker($broker)->createToken($this);
+ }
+
+ public function generateActivateAccountToken()
+ {
+ $broker = config('statamic.users.passwords.'.PasswordReset::BROKER_ACTIVATIONS);
+
+ return Password::broker($broker)->createToken($this);
}
public static function __callStatic($method, $parameters)
diff --git a/src/Http/Controllers/ActivateAccountController.php b/src/Http/Controllers/ActivateAccountController.php
new file mode 100644
index 0000000000..f8f14e68c5
--- /dev/null
+++ b/src/Http/Controllers/ActivateAccountController.php
@@ -0,0 +1,24 @@
+invitation['send']) {
ActivateAccount::subject($request->invitation['subject']);
ActivateAccount::body($request->invitation['message']);
- $user->generateTokenAndSendPasswordResetNotification();
+ $user->generateTokenAndSendActivateAccountNotification();
+ $url = null;
+ } else {
+ $url = PasswordReset::url($user->generateActivateAccountToken(), PasswordReset::BROKER_ACTIVATIONS);
}
return [
'redirect' => $user->editUrl(),
- 'activationUrl' => $request->invitation['send'] ? null : $user->getPasswordResetUrl(),
+ 'activationUrl' => $url,
];
}
diff --git a/src/Http/Controllers/ForgotPasswordController.php b/src/Http/Controllers/ForgotPasswordController.php
index 9e708fbb58..df7bcb24c8 100644
--- a/src/Http/Controllers/ForgotPasswordController.php
+++ b/src/Http/Controllers/ForgotPasswordController.php
@@ -3,6 +3,7 @@
namespace Statamic\Http\Controllers;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Password;
use Statamic\Auth\Passwords\PasswordReset;
use Statamic\Auth\SendsPasswordResetEmails;
use Statamic\Facades\URL;
@@ -32,4 +33,9 @@ public function sendResetLinkEmail(Request $request)
return $this->traitSendResetLinkEmail($request);
}
+
+ public function broker()
+ {
+ return Password::broker(PasswordReset::BROKER_RESETS);
+ }
}
diff --git a/src/Http/Controllers/ResetPasswordController.php b/src/Http/Controllers/ResetPasswordController.php
index 2ff6b571ed..24960cf404 100644
--- a/src/Http/Controllers/ResetPasswordController.php
+++ b/src/Http/Controllers/ResetPasswordController.php
@@ -3,6 +3,8 @@
namespace Statamic\Http\Controllers;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Password;
+use Statamic\Auth\Passwords\PasswordReset;
use Statamic\Auth\ResetsPasswords;
use Statamic\Http\Middleware\RedirectIfAuthenticated;
@@ -19,9 +21,22 @@ public function __construct()
public function showResetForm(Request $request, $token = null)
{
- return view('statamic::auth.passwords.reset')->with(
- ['token' => $token, 'email' => $request->email]
- );
+ return view('statamic::auth.passwords.reset')->with([
+ 'token' => $token,
+ 'email' => $request->email,
+ 'action' => $this->resetFormAction(),
+ 'title' => $this->resetFormTitle(),
+ ]);
+ }
+
+ protected function resetFormAction()
+ {
+ return route('statamic.password.reset.action');
+ }
+
+ protected function resetFormTitle()
+ {
+ return __('Reset Password');
}
public function redirectPath()
@@ -38,4 +53,9 @@ protected function resetPassword($user, $password)
$this->traitResetPassword($user, $password);
}
+
+ public function broker()
+ {
+ return Password::broker(PasswordReset::BROKER_RESETS);
+ }
}
diff --git a/src/Notifications/ActivateAccount.php b/src/Notifications/ActivateAccount.php
index 226a511381..921efff35e 100644
--- a/src/Notifications/ActivateAccount.php
+++ b/src/Notifications/ActivateAccount.php
@@ -39,7 +39,7 @@ public function toMail($notifiable)
return (new MailMessage)
->subject(static::$subject ?? __('statamic::messages.activate_account_notification_subject'))
->line(static::$body ?? __('statamic::messages.activate_account_notification_body'))
- ->action(__('Activate Account'), PasswordResetManager::url($this->token));
+ ->action(__('Activate Account'), PasswordResetManager::url($this->token, PasswordResetManager::BROKER_ACTIVATIONS));
}
/**
diff --git a/src/Notifications/PasswordReset.php b/src/Notifications/PasswordReset.php
index e908eb2c80..63b0cfd712 100644
--- a/src/Notifications/PasswordReset.php
+++ b/src/Notifications/PasswordReset.php
@@ -5,7 +5,7 @@
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
-use Statamic\Auth\Passwords\PasswordReset as PasswordResetUrl;
+use Statamic\Auth\Passwords\PasswordReset as PasswordResetManager;
class PasswordReset extends Notification
{
@@ -40,7 +40,7 @@ public function toMail($notifiable)
return (new MailMessage)
->subject(__('statamic::messages.reset_password_notification_subject'))
->line(__('statamic::messages.reset_password_notification_body'))
- ->action(__('Reset Password'), PasswordResetUrl::url($this->token))
+ ->action(__('Reset Password'), PasswordResetManager::url($this->token, PasswordResetManager::BROKER_RESETS))
->line(__('statamic::messages.reset_password_notification_no_action'));
}