mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge pull request #1507 from aztech-dev/recovery
Extract password recovery logic in service
This commit is contained in:
61
lib/Alchemy/Phrasea/Account/CollectionRequestMapper.php
Normal file
61
lib/Alchemy/Phrasea/Account/CollectionRequestMapper.php
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Account;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application;
|
||||||
|
use Alchemy\Phrasea\Core\Configuration\RegistrationManager;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\User;
|
||||||
|
|
||||||
|
class CollectionRequestMapper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Application
|
||||||
|
*/
|
||||||
|
private $app;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var RegistrationManager
|
||||||
|
*/
|
||||||
|
private $registrationManager;
|
||||||
|
|
||||||
|
public function __construct(Application $app, RegistrationManager $registrationManager)
|
||||||
|
{
|
||||||
|
$this->app = $app;
|
||||||
|
$this->registrationManager = $registrationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserRequests(User $user)
|
||||||
|
{
|
||||||
|
$databoxStatuses = $this->registrationManager->getRegistrationSummary($user);
|
||||||
|
|
||||||
|
$demands = array();
|
||||||
|
|
||||||
|
foreach ($databoxStatuses as $databoxId => $data) {
|
||||||
|
foreach ($data['registrations']['by-type']['pending'] as $collectionId => $waiting) {
|
||||||
|
$demands[] = $this->mapCollectionStatus($databoxId, $collectionId, "pending");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data['registrations']['by-type']['rejected'] as $collectionId => $waiting) {
|
||||||
|
$demands[] = $this->mapCollectionStatus($databoxId, $collectionId, "rejected");
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data['registrations']['by-type']['accepted'] as $collectionId => $waiting) {
|
||||||
|
$demands[] = $this->mapCollectionStatus($databoxId, $collectionId, "accepted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $demands;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function mapCollectionStatus($databoxId, $collectionId, $status)
|
||||||
|
{
|
||||||
|
$baseId = \phrasea::baseFromColl($databoxId, $collectionId, $this->app);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
"databox_id" => $databoxId,
|
||||||
|
"base_id" => $baseId,
|
||||||
|
"collection_id" => $collectionId,
|
||||||
|
"status" => $status
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
150
lib/Alchemy/Phrasea/Authentication/RecoveryService.php
Normal file
150
lib/Alchemy/Phrasea/Authentication/RecoveryService.php
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Alchemy\Phrasea\Authentication;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application;
|
||||||
|
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\User;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||||
|
use Alchemy\Phrasea\Model\Repositories\TokenRepository;
|
||||||
|
use Alchemy\Phrasea\Model\Repositories\UserRepository;
|
||||||
|
use Alchemy\Phrasea\Notification\Deliverer;
|
||||||
|
use Alchemy\Phrasea\Notification\Mail\MailRequestPasswordUpdate;
|
||||||
|
use Alchemy\Phrasea\Notification\Receiver;
|
||||||
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
|
|
||||||
|
class RecoveryService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Application
|
||||||
|
*/
|
||||||
|
private $application;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Deliverer
|
||||||
|
*/
|
||||||
|
private $mailer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TokenManipulator
|
||||||
|
*/
|
||||||
|
private $tokenManipulator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TokenRepository
|
||||||
|
*/
|
||||||
|
private $tokenRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var UserManipulator
|
||||||
|
*/
|
||||||
|
private $userManipulator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var UserRepository
|
||||||
|
*/
|
||||||
|
private $userRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var UrlGeneratorInterface
|
||||||
|
*/
|
||||||
|
private $urlGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Application $application
|
||||||
|
* @param Deliverer $mailer
|
||||||
|
* @param TokenManipulator $tokenManipulator
|
||||||
|
* @param TokenRepository $tokenRepository
|
||||||
|
* @param UserManipulator $userManipulator
|
||||||
|
* @param UserRepository $userRepository
|
||||||
|
* @param UrlGeneratorInterface $urlGenerator
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Application $application,
|
||||||
|
Deliverer $mailer,
|
||||||
|
TokenManipulator $tokenManipulator,
|
||||||
|
TokenRepository $tokenRepository,
|
||||||
|
UserManipulator $userManipulator,
|
||||||
|
UserRepository $userRepository,
|
||||||
|
UrlGeneratorInterface $urlGenerator
|
||||||
|
) {
|
||||||
|
$this->application = $application;
|
||||||
|
$this->mailer = $mailer;
|
||||||
|
$this->tokenManipulator = $tokenManipulator;
|
||||||
|
$this->tokenRepository = $tokenRepository;
|
||||||
|
$this->userManipulator = $userManipulator;
|
||||||
|
$this->userRepository = $userRepository;
|
||||||
|
$this->urlGenerator = $urlGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $email
|
||||||
|
* @param bool $notifyUser
|
||||||
|
* @return string
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function requestPasswordResetToken($email, $notifyUser = true)
|
||||||
|
{
|
||||||
|
$user = $this->userRepository->findByEmail($email);
|
||||||
|
|
||||||
|
if (! $user) {
|
||||||
|
throw new InvalidArgumentException('phraseanet::erreur: Le compte n\'a pas ete trouve');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->requestPasswordResetTokenByUser($user, $notifyUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $login
|
||||||
|
* @param bool $notifyUser
|
||||||
|
* @return string
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function requestPasswordResetTokenByLogin($login, $notifyUser = true)
|
||||||
|
{
|
||||||
|
$user = $this->userRepository->findByLogin($login);
|
||||||
|
|
||||||
|
if (! $user) {
|
||||||
|
throw new InvalidArgumentException('phraseanet::erreur: Le compte n\'a pas ete trouve');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->requestPasswordResetTokenByUser($user, $notifyUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
* @param bool $notifyUser
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function requestPasswordResetTokenByUser(User $user, $notifyUser = true)
|
||||||
|
{
|
||||||
|
$receiver = Receiver::fromUser($user);
|
||||||
|
$token = $this->tokenManipulator->createResetPasswordToken($user);
|
||||||
|
|
||||||
|
if ($notifyUser) {
|
||||||
|
$url = $this->urlGenerator->generate('login_renew_password', [ 'token' => $token->getValue() ], true);
|
||||||
|
|
||||||
|
$mail = MailRequestPasswordUpdate::create($this->application, $receiver);
|
||||||
|
$mail->setLogin($user->getLogin());
|
||||||
|
$mail->setButtonUrl($url);
|
||||||
|
$mail->setExpiration(new \DateTime('+1 day'));
|
||||||
|
|
||||||
|
$this->mailer->deliver($mail);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetPassword($resetToken, $newPassword)
|
||||||
|
{
|
||||||
|
$token = $this->tokenRepository->findValidToken($resetToken);
|
||||||
|
|
||||||
|
if ($token === null || $token->getType() != TokenManipulator::TYPE_PASSWORD) {
|
||||||
|
$this->application->abort(401, 'A token is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->userManipulator->setPassword($token->getUser(), $newPassword);
|
||||||
|
$this->tokenManipulator->delete($token);
|
||||||
|
}
|
||||||
|
}
|
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
namespace Alchemy\Phrasea\Controller\Api;
|
namespace Alchemy\Phrasea\Controller\Api;
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Account\CollectionRequestMapper;
|
||||||
use Alchemy\Phrasea\Application\Helper\DataboxLoggerAware;
|
use Alchemy\Phrasea\Application\Helper\DataboxLoggerAware;
|
||||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||||
use Alchemy\Phrasea\Authentication\Context;
|
use Alchemy\Phrasea\Authentication\Context;
|
||||||
@@ -782,6 +783,42 @@ class V1Controller extends Controller
|
|||||||
return $grants;
|
return $grants;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function listUserDemands(User $user)
|
||||||
|
{
|
||||||
|
return (new CollectionRequestMapper($this->app, $this->app['registration.manager']))->getUserRequests($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resetPassword(Request $request, $email)
|
||||||
|
{
|
||||||
|
/** @var \Alchemy\Phrasea\Authentication\RecoveryService $service */
|
||||||
|
$service = $this->app['authentication.recovery_service'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$token = $service->requestPasswordResetToken($email, false);
|
||||||
|
}
|
||||||
|
catch (\Exception $exception) {
|
||||||
|
$token = $service->requestPasswordResetTokenByLogin($email, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result::create($request, [ 'reset_token' => $token ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setNewPassword(Request $request, $token)
|
||||||
|
{
|
||||||
|
$password = $request->request->get('password', null);
|
||||||
|
/** @var \Alchemy\Phrasea\Authentication\RecoveryService $service */
|
||||||
|
$service = $this->app['authentication.recovery_service'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$service->resetPassword($token, $password);
|
||||||
|
}
|
||||||
|
catch (\Exception $exception) {
|
||||||
|
return Result::create($request, [ 'success' => false ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result::create($request, [ 'success' => true ]);
|
||||||
|
}
|
||||||
|
|
||||||
public function addRecordAction(Request $request)
|
public function addRecordAction(Request $request)
|
||||||
{
|
{
|
||||||
if (count($request->files->get('file')) == 0) {
|
if (count($request->files->get('file')) == 0) {
|
||||||
@@ -1036,7 +1073,6 @@ class V1Controller extends Controller
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($record->isStory()) {
|
if ($record->isStory()) {
|
||||||
$ret['results']['stories'][] = $this->listStory($request, $record);
|
$ret['results']['stories'][] = $this->listStory($request, $record);
|
||||||
} else {
|
} else {
|
||||||
@@ -2299,6 +2335,12 @@ class V1Controller extends Controller
|
|||||||
"collections" => $this->listUserCollections($this->getAuthenticatedUser())
|
"collections" => $this->listUserCollections($this->getAuthenticatedUser())
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (! constant('API_SKIP_USER_REGISTRATIONS')) {
|
||||||
|
// I am infinitely sorry... if you feel like it, you can fix the tests database bootstrapping
|
||||||
|
// to use SQLite in all cases and remove this check. Good luck...
|
||||||
|
$ret["demands"] = $this->listUserDemands($this->getAuthenticatedUser());
|
||||||
|
}
|
||||||
|
|
||||||
return Result::create($request, $ret)->createResponse();
|
return Result::create($request, $ret)->createResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,10 +16,11 @@ use Alchemy\Phrasea\Authentication\AccountCreator;
|
|||||||
use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
|
use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
|
||||||
use Alchemy\Phrasea\Authentication\Exception\AuthenticationException;
|
use Alchemy\Phrasea\Authentication\Exception\AuthenticationException;
|
||||||
use Alchemy\Phrasea\Authentication\Context;
|
use Alchemy\Phrasea\Authentication\Context;
|
||||||
use Alchemy\Phrasea\Authentication\Phrasea\NativeAuthentication;
|
use Alchemy\Phrasea\Authentication\Phrasea\PasswordAuthenticationInterface;
|
||||||
use Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder;
|
use Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder;
|
||||||
use Alchemy\Phrasea\Authentication\Provider\ProviderInterface;
|
use Alchemy\Phrasea\Authentication\Provider\ProviderInterface;
|
||||||
use Alchemy\Phrasea\Authentication\ProvidersCollection;
|
use Alchemy\Phrasea\Authentication\ProvidersCollection;
|
||||||
|
use Alchemy\Phrasea\Authentication\RecoveryService;
|
||||||
use Alchemy\Phrasea\Authentication\SuggestionFinder;
|
use Alchemy\Phrasea\Authentication\SuggestionFinder;
|
||||||
use Alchemy\Phrasea\Controller\Controller;
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
use Alchemy\Phrasea\Core\Configuration\ConfigurationInterface;
|
use Alchemy\Phrasea\Core\Configuration\ConfigurationInterface;
|
||||||
@@ -470,23 +471,17 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
public function renewPassword(Request $request)
|
public function renewPassword(Request $request)
|
||||||
{
|
{
|
||||||
if (null === $tokenValue = $request->get('token')) {
|
$service = $this->getRecoveryService();
|
||||||
$this->app->abort(401, 'A token is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $token = $this->getTokenRepository()->findValidToken($tokenValue)) {
|
|
||||||
$this->app->abort(401, 'A token is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
$form = $this->app->form(new PhraseaRecoverPasswordForm($this->getTokenRepository()));
|
$form = $this->app->form(new PhraseaRecoverPasswordForm($this->getTokenRepository()));
|
||||||
$form->setData(['token' => $token->getValue()]);
|
$form->setData(['token' => $request->get('token') ]);
|
||||||
|
|
||||||
if ('POST' === $request->getMethod()) {
|
if ('POST' === $request->getMethod()) {
|
||||||
$form->handleRequest($request);
|
$form->handleRequest($request);
|
||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$data = $form->getData();
|
$data = $form->getData();
|
||||||
$this->getUserManipulator()->setPassword($token->getUser(), $data['password']);
|
|
||||||
$this->getTokenManipulator()->delete($token);
|
$service->resetPassword($data['token'], $data['password']);
|
||||||
$this->app->addFlash('success', $this->app->trans('login::notification: Mise a jour du mot de passe avec succes'));
|
$this->app->addFlash('success', $this->app->trans('login::notification: Mise a jour du mot de passe avec succes'));
|
||||||
|
|
||||||
return $this->app->redirectPath('homepage');
|
return $this->app->redirectPath('homepage');
|
||||||
@@ -495,7 +490,7 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
return $this->render('login/renew-password.html.twig', array_merge(
|
return $this->render('login/renew-password.html.twig', array_merge(
|
||||||
$this->getDefaultTemplateVariables($request),
|
$this->getDefaultTemplateVariables($request),
|
||||||
['form' => $form->createView()]
|
['form' => $form->createView() ]
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,6 +503,7 @@ class LoginController extends Controller
|
|||||||
public function forgotPassword(Request $request)
|
public function forgotPassword(Request $request)
|
||||||
{
|
{
|
||||||
$form = $this->app->form(new PhraseaForgotPasswordForm());
|
$form = $this->app->form(new PhraseaForgotPasswordForm());
|
||||||
|
$service = $this->getRecoveryService();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ('POST' === $request->getMethod()) {
|
if ('POST' === $request->getMethod()) {
|
||||||
@@ -516,27 +512,13 @@ class LoginController extends Controller
|
|||||||
if ($form->isValid()) {
|
if ($form->isValid()) {
|
||||||
$data = $form->getData();
|
$data = $form->getData();
|
||||||
|
|
||||||
if (null === $user = $this->getUserRepository()->findByEmail($data['email'])) {
|
|
||||||
throw new FormProcessingException(_('phraseanet::erreur: Le compte n\'a pas ete trouve'));
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$receiver = Receiver::fromUser($user);
|
$service->requestPasswordResetToken($data['email'], true);
|
||||||
} catch (InvalidArgumentException $e) {
|
}
|
||||||
throw new FormProcessingException($this->app->trans('Invalid email address'));
|
catch (InvalidArgumentException $ex) {
|
||||||
|
throw new FormProcessingException($this->app->trans($ex->getMessage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = $this->getTokenManipulator()->createResetPasswordToken($user);
|
|
||||||
|
|
||||||
$url = $this->app->url('login_renew_password', ['token' => $token->getValue()], true);
|
|
||||||
|
|
||||||
$expirationDate = new \DateTime('+1 day');
|
|
||||||
$mail = MailRequestPasswordUpdate::create($this->app, $receiver);
|
|
||||||
$mail->setLogin($user->getLogin());
|
|
||||||
$mail->setButtonUrl($url);
|
|
||||||
$mail->setExpiration($expirationDate);
|
|
||||||
|
|
||||||
$this->deliver($mail);
|
|
||||||
$this->app->addFlash('info', $this->app->trans('phraseanet:: Un email vient de vous etre envoye'));
|
$this->app->addFlash('info', $this->app->trans('phraseanet:: Un email vient de vous etre envoye'));
|
||||||
|
|
||||||
return $this->app->redirectPath('login_forgot_password');
|
return $this->app->redirectPath('login_forgot_password');
|
||||||
@@ -548,9 +530,8 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
return $this->render('login/forgot-password.html.twig', array_merge(
|
return $this->render('login/forgot-password.html.twig', array_merge(
|
||||||
$this->getDefaultTemplateVariables($request),
|
$this->getDefaultTemplateVariables($request),
|
||||||
[
|
[ 'form' => $form->createView() ]
|
||||||
'form' => $form->createView(),
|
));
|
||||||
]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -698,8 +679,8 @@ class LoginController extends Controller
|
|||||||
public function postAuthProcess(Request $request, User $user)
|
public function postAuthProcess(Request $request, User $user)
|
||||||
{
|
{
|
||||||
$date = new \DateTime('+' . (int) $this->getConf()->get(['registry', 'actions', 'validation-reminder-days']) . ' days');
|
$date = new \DateTime('+' . (int) $this->getConf()->get(['registry', 'actions', 'validation-reminder-days']) . ' days');
|
||||||
|
|
||||||
$manager = $this->getEntityManager();
|
$manager = $this->getEntityManager();
|
||||||
|
|
||||||
foreach ($this->getValidationParticipantRepository()->findNotConfirmedAndNotRemindedParticipantsByExpireDate($date) as $participant) {
|
foreach ($this->getValidationParticipantRepository()->findNotConfirmedAndNotRemindedParticipantsByExpireDate($date) as $participant) {
|
||||||
$validationSession = $participant->getSession();
|
$validationSession = $participant->getSession();
|
||||||
$basket = $validationSession->getBasket();
|
$basket = $validationSession->getBasket();
|
||||||
@@ -862,8 +843,11 @@ class LoginController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$usr_id = $this->getNativeAuthentication()
|
$usr_id = $this->getPasswordAuthentication()->getUsrId(
|
||||||
->getUsrId($request->request->get('login'), $request->request->get('password'), $request);
|
$request->request->get('login'),
|
||||||
|
$request->request->get('password'),
|
||||||
|
$request
|
||||||
|
);
|
||||||
} catch (RequireCaptchaException $e) {
|
} catch (RequireCaptchaException $e) {
|
||||||
$this->app->requireCaptcha();
|
$this->app->requireCaptcha();
|
||||||
$this->app->addFlash('warning', $this->app->trans('Please fill the captcha'));
|
$this->app->addFlash('warning', $this->app->trans('Please fill the captcha'));
|
||||||
@@ -883,7 +867,6 @@ class LoginController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->getUserRepository()->find($usr_id);
|
$user = $this->getUserRepository()->find($usr_id);
|
||||||
|
|
||||||
$session = $this->postAuthProcess($request, $user);
|
$session = $this->postAuthProcess($request, $user);
|
||||||
|
|
||||||
$response = $this->generateAuthResponse($this->getBrowser(), $request->request->get('redirect'));
|
$response = $this->generateAuthResponse($this->getBrowser(), $request->request->get('redirect'));
|
||||||
@@ -1064,9 +1047,9 @@ class LoginController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return NativeAuthentication
|
* @return PasswordAuthenticationInterface
|
||||||
*/
|
*/
|
||||||
private function getNativeAuthentication()
|
private function getPasswordAuthentication()
|
||||||
{
|
{
|
||||||
return $this->app['auth.native'];
|
return $this->app['auth.native'];
|
||||||
}
|
}
|
||||||
@@ -1086,4 +1069,12 @@ class LoginController extends Controller
|
|||||||
{
|
{
|
||||||
return $this->app['configuration.store'];
|
return $this->app['configuration.store'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return RecoveryService
|
||||||
|
*/
|
||||||
|
private function getRecoveryService()
|
||||||
|
{
|
||||||
|
return $this->app['authentication.recovery_service'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -249,6 +249,12 @@ class V1 implements ControllerProviderInterface, ServiceProviderInterface
|
|||||||
|
|
||||||
$controllers->get('/me/', 'controller.api.v1:getCurrentUserAction');
|
$controllers->get('/me/', 'controller.api.v1:getCurrentUserAction');
|
||||||
|
|
||||||
|
$controllers->post('/accounts/reset-password/{login}/', 'controller.api.v1:resetPassword')
|
||||||
|
->before('controller.api.v1:ensureAdmin');
|
||||||
|
|
||||||
|
$controllers->post('/accounts/update-password/{token}/', 'controller.api.v1:setNewPassword')
|
||||||
|
->before('controller.api.v1:ensureAdmin');
|
||||||
|
|
||||||
return $controllers;
|
return $controllers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -22,6 +22,7 @@ use Alchemy\Phrasea\Authentication\Phrasea\FailureHandledNativeAuthentication;
|
|||||||
use Alchemy\Phrasea\Authentication\Phrasea\NativeAuthentication;
|
use Alchemy\Phrasea\Authentication\Phrasea\NativeAuthentication;
|
||||||
use Alchemy\Phrasea\Authentication\Phrasea\OldPasswordEncoder;
|
use Alchemy\Phrasea\Authentication\Phrasea\OldPasswordEncoder;
|
||||||
use Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder;
|
use Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder;
|
||||||
|
use Alchemy\Phrasea\Authentication\RecoveryService;
|
||||||
use Alchemy\Phrasea\Authentication\SuggestionFinder;
|
use Alchemy\Phrasea\Authentication\SuggestionFinder;
|
||||||
use Silex\Application;
|
use Silex\Application;
|
||||||
use Silex\ServiceProviderInterface;
|
use Silex\ServiceProviderInterface;
|
||||||
@@ -87,6 +88,18 @@ class AuthenticationManagerServiceProvider implements ServiceProviderInterface
|
|||||||
return new Manager($app['authentication'], $app['authentication.providers']);
|
return new Manager($app['authentication'], $app['authentication.providers']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$app['authentication.recovery_service'] = $app->share(function (Application $app) {
|
||||||
|
return new RecoveryService(
|
||||||
|
$app,
|
||||||
|
$app['notification.deliverer'],
|
||||||
|
$app['manipulator.token'],
|
||||||
|
$app['repo.tokens'],
|
||||||
|
$app['manipulator.user'],
|
||||||
|
$app['repo.users'],
|
||||||
|
$app['url_generator']
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
$app['auth.password-encoder'] = $app->share(function (Application $app) {
|
$app['auth.password-encoder'] = $app->share(function (Application $app) {
|
||||||
return new PasswordEncoder($app['conf']->get(['main','key']));
|
return new PasswordEncoder($app['conf']->get(['main','key']));
|
||||||
});
|
});
|
||||||
|
@@ -177,7 +177,7 @@ class Token
|
|||||||
/**
|
/**
|
||||||
* Set expiration
|
* Set expiration
|
||||||
*
|
*
|
||||||
* @param \DateTime $updated
|
* @param \DateTime $expiration
|
||||||
* @return Token
|
* @return Token
|
||||||
*/
|
*/
|
||||||
public function setExpiration(\DateTime $expiration = null)
|
public function setExpiration(\DateTime $expiration = null)
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
<php>
|
<php>
|
||||||
<ini name="display_errors" value="on"/>
|
<ini name="display_errors" value="on"/>
|
||||||
<ini name="memory_limit" value="2G"/>
|
<ini name="memory_limit" value="2G"/>
|
||||||
|
<const name="API_SKIP_USER_REGISTRATIONS" value="true" />
|
||||||
</php>
|
</php>
|
||||||
|
|
||||||
<testsuites>
|
<testsuites>
|
||||||
|
@@ -332,7 +332,7 @@ class LoginTest extends \PhraseanetAuthenticatedWebTestCase
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$response = self::$DI['client']->getResponse();
|
$response = self::$DI['client']->getResponse();
|
||||||
$this->assertEquals(401, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRenewPasswordBadTokenWheneverItsAuthenticated()
|
public function testRenewPasswordBadTokenWheneverItsAuthenticated()
|
||||||
@@ -359,7 +359,7 @@ class LoginTest extends \PhraseanetAuthenticatedWebTestCase
|
|||||||
|
|
||||||
$response = self::$DI['client']->getResponse();
|
$response = self::$DI['client']->getResponse();
|
||||||
|
|
||||||
$this->assertEquals(401, $response->getStatusCode());
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRenewPasswordNoTokenWheneverItsAuthenticated()
|
public function testRenewPasswordNoTokenWheneverItsAuthenticated()
|
||||||
|
@@ -30,7 +30,6 @@ abstract class PhraseanetTestCase extends WebTestCase
|
|||||||
const USER_AGENT_IE6 = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)';
|
const USER_AGENT_IE6 = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)';
|
||||||
const USER_AGENT_IPHONE = 'Mozilla/5.0 (iPod; U; CPU iPhone OS 2_1 like Mac OS X; fr-fr) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5F137 Safari/525.20';
|
const USER_AGENT_IPHONE = 'Mozilla/5.0 (iPod; U; CPU iPhone OS 2_1 like Mac OS X; fr-fr) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5F137 Safari/525.20';
|
||||||
|
|
||||||
|
|
||||||
protected static $DI;
|
protected static $DI;
|
||||||
|
|
||||||
private static $recordsInitialized = false;
|
private static $recordsInitialized = false;
|
||||||
|
Reference in New Issue
Block a user