Compare commits
3 Commits
v1.0.6
...
4f8c26fc66
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f8c26fc66 | |||
| 81841a88a6 | |||
| 149c5f560a |
@@ -16,4 +16,6 @@ $app->group('/account', function () {
|
|||||||
$this->get('/register', 'UserFrosting\Sprinkle\UFTweaks\Controller\AccountController:pageRegister')
|
$this->get('/register', 'UserFrosting\Sprinkle\UFTweaks\Controller\AccountController:pageRegister')
|
||||||
->add('checkEnvironment')
|
->add('checkEnvironment')
|
||||||
->setName('register');
|
->setName('register');
|
||||||
|
|
||||||
|
$this->post('/forgot-password', 'UserFrosting\Sprinkle\UFTweaks\Controller\AccountController:forgotPassword');
|
||||||
})->add(new NoCache());
|
})->add(new NoCache());
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
namespace UserFrosting\Sprinkle\UFTweaks\Controller;
|
namespace UserFrosting\Sprinkle\UFTweaks\Controller;
|
||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Database\Capsule\Manager as Capsule;
|
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||||
use Psr\Http\Message\ResponseInterface as Response;
|
use Psr\Http\Message\ResponseInterface as Response;
|
||||||
@@ -18,6 +19,9 @@ use UserFrosting\Fortress\RequestDataTransformer;
|
|||||||
use UserFrosting\Fortress\RequestSchema;
|
use UserFrosting\Fortress\RequestSchema;
|
||||||
use UserFrosting\Fortress\ServerSideValidator;
|
use UserFrosting\Fortress\ServerSideValidator;
|
||||||
use UserFrosting\Sprinkle\Account\Controller\AccountController as UFAccountController;
|
use UserFrosting\Sprinkle\Account\Controller\AccountController as UFAccountController;
|
||||||
|
use UserFrosting\Sprinkle\Account\Facades\Password;
|
||||||
|
use UserFrosting\Sprinkle\Core\Mail\EmailRecipient;
|
||||||
|
use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage;
|
||||||
use UserFrosting\Support\Exception\BadRequestException;
|
use UserFrosting\Support\Exception\BadRequestException;
|
||||||
use UserFrosting\Support\Exception\ForbiddenException;
|
use UserFrosting\Support\Exception\ForbiddenException;
|
||||||
use UserFrosting\Support\Exception\NotFoundException;
|
use UserFrosting\Support\Exception\NotFoundException;
|
||||||
@@ -29,6 +33,111 @@ use UserFrosting\Support\Exception\NotFoundException;
|
|||||||
*/
|
*/
|
||||||
class AccountController extends UFAccountController
|
class AccountController extends UFAccountController
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Processes a request to email a forgotten password reset link to the user.
|
||||||
|
*
|
||||||
|
* Processes the request from the form on the "forgot password" page, checking that:
|
||||||
|
* 1. The rate limit for this type of request is being observed.
|
||||||
|
* 2. The provided email address belongs to a registered account;
|
||||||
|
* 3. The submitted data is valid.
|
||||||
|
* Note that we have removed the requirement that a password reset request not already be in progress.
|
||||||
|
* This is because we need to allow users to re-request a reset, even if they lose the first reset email.
|
||||||
|
* This route is "public access".
|
||||||
|
*
|
||||||
|
* @todo require additional user information
|
||||||
|
* @todo prevent password reset requests for root account?
|
||||||
|
*
|
||||||
|
* AuthGuard: false
|
||||||
|
* Route: /account/forgot-password
|
||||||
|
* Route Name: {none}
|
||||||
|
* Request type: POST
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @param Response $response
|
||||||
|
* @param array $args
|
||||||
|
*/
|
||||||
|
public function forgotPassword(Request $request, Response $response, $args)
|
||||||
|
{
|
||||||
|
/** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */
|
||||||
|
$ms = $this->ci->alerts;
|
||||||
|
|
||||||
|
/** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */
|
||||||
|
$classMapper = $this->ci->classMapper;
|
||||||
|
|
||||||
|
/** @var \UserFrosting\Support\Repository\Repository $config */
|
||||||
|
$config = $this->ci->config;
|
||||||
|
|
||||||
|
// Get POST parameters
|
||||||
|
$params = $request->getParsedBody();
|
||||||
|
|
||||||
|
// Load the request schema
|
||||||
|
$schema = new RequestSchema('schema://requests/forgot-password.yaml');
|
||||||
|
|
||||||
|
// Whitelist and set parameter defaults
|
||||||
|
$transformer = new RequestDataTransformer($schema);
|
||||||
|
$data = $transformer->transform($params);
|
||||||
|
|
||||||
|
// Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit.
|
||||||
|
$validator = new ServerSideValidator($schema, $this->ci->translator);
|
||||||
|
if (!$validator->validate($data)) {
|
||||||
|
$ms->addValidationErrors($validator);
|
||||||
|
|
||||||
|
return $response->withJson([], 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throttle requests
|
||||||
|
/** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */
|
||||||
|
$throttler = $this->ci->throttler;
|
||||||
|
|
||||||
|
$throttleData = [
|
||||||
|
'email' => $data['email'],
|
||||||
|
];
|
||||||
|
$delay = $throttler->getDelay('password_reset_request', $throttleData);
|
||||||
|
|
||||||
|
if ($delay > 0) {
|
||||||
|
$ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]);
|
||||||
|
|
||||||
|
return $response->withJson([], 429);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the user, by email address
|
||||||
|
$user = $classMapper->getClassMapping('user')::where('email', $data['email'])->first();
|
||||||
|
|
||||||
|
if ($user) {
|
||||||
|
if (!$user->flag_verified) {
|
||||||
|
$ms->addMessageTranslated('danger', 'ACCOUNT.UNVERIFIED');
|
||||||
|
return $response->withJson([], 400);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All checks passed! log events/activities, update user, and send email
|
||||||
|
// Begin transaction - DB will be rolled back if an exception occurs
|
||||||
|
Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config, $user) {
|
||||||
|
// Log throttleable event
|
||||||
|
$throttler->logEvent('password_reset_request', $throttleData);
|
||||||
|
|
||||||
|
// Check that the email exists.
|
||||||
|
// If there is no user with that email address, we should still pretend like we succeeded, to prevent account enumeration
|
||||||
|
if ($user) {
|
||||||
|
// Try to generate a new password reset request.
|
||||||
|
// Use timeout for "reset password"
|
||||||
|
$passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']);
|
||||||
|
|
||||||
|
// Create and send email
|
||||||
|
$message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig');
|
||||||
|
$message->from($config['address_book.admin'])
|
||||||
|
->addEmailRecipient(new EmailRecipient($user->email, $user->full_name))
|
||||||
|
->addParams([
|
||||||
|
'user' => $user,
|
||||||
|
'token' => $passwordReset->getToken(),
|
||||||
|
'request_date' => Carbon::now()->format('Y-m-d H:i:s'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->ci->mailer->send($message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Account settings page.
|
* Account settings page.
|
||||||
*
|
*
|
||||||
|
|||||||
43
src/Scheduler/Tasks/CleanupSessions.php
Normal file
43
src/Scheduler/Tasks/CleanupSessions.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AVSDev UF Tweaks (https://avsdev.uk)
|
||||||
|
*
|
||||||
|
* @link https://git.avsdev.uk/avsdev/sprinkle-uf-tweaks
|
||||||
|
* @license https://git.avsdev.uk/avsdev/sprinkle-uf-tweaks/blob/master/LICENSE.md (LGPL-3.0 License)
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace UserFrosting\Sprinkle\UFTweaks\Scheduler\Tasks;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Database\Capsule\Manager as Capsule;
|
||||||
|
use UserFrosting\Sprinkle\Scheduler\Scheduler\BaseTask;
|
||||||
|
use UserFrosting\Sprinkle\Core\Database\Models\Session;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daily task to clean expired sessions from the database
|
||||||
|
*
|
||||||
|
* @author Craig Williams (https://avsdev.uk)
|
||||||
|
*/
|
||||||
|
class CleanupSessions extends BaseTask
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Function used to specify the schedule for the task.
|
||||||
|
*/
|
||||||
|
public function schedule()
|
||||||
|
{
|
||||||
|
$this->daily()->at("23:00");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used to specify what the task does.
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// Remove sessions over 2 days old
|
||||||
|
Session::where('last_activity', '<', time()-(60*60*48))->delete();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user