563 lines
21 KiB
PHP
563 lines
21 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace In2code\Femanager\Controller;
|
|
|
|
use In2code\Femanager\Domain\Model\Log;
|
|
use In2code\Femanager\Domain\Model\User;
|
|
use In2code\Femanager\Domain\Service\AutoAdminConfirmationService;
|
|
use In2code\Femanager\Event\BeforeUserConfirmEvent;
|
|
use In2code\Femanager\Event\BeforeUserCreateEvent;
|
|
use In2code\Femanager\Event\CreateConfirmationRequestEvent;
|
|
use In2code\Femanager\Utility\ConfigurationUtility;
|
|
use In2code\Femanager\Utility\FrontendUtility;
|
|
use In2code\Femanager\Utility\HashUtility;
|
|
use In2code\Femanager\Utility\LocalizationUtility;
|
|
use In2code\Femanager\Utility\StringUtility;
|
|
use In2code\Femanager\Utility\UserUtility;
|
|
use Psr\Http\Message\ResponseInterface;
|
|
use TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException;
|
|
use TYPO3\CMS\Core\Http\ServerRequestFactory;
|
|
use TYPO3\CMS\Core\Messaging\AbstractMessage;
|
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
|
use TYPO3\CMS\Extbase\Annotation\Validate;
|
|
use TYPO3\CMS\Extbase\Event\Mvc\AfterRequestDispatchedEvent;
|
|
use TYPO3\CMS\Extbase\Mvc\Exception\StopActionException;
|
|
use TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException;
|
|
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
|
|
|
|
/**
|
|
* Class NewController
|
|
*/
|
|
class NewController extends AbstractFrontendController
|
|
{
|
|
/**
|
|
* Render registration form
|
|
*
|
|
*/
|
|
public function newAction(): ResponseInterface
|
|
{
|
|
$this->view->assignMultiple(
|
|
[
|
|
'allUserGroups' => $this->allUserGroups
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
|
|
/**
|
|
* action create
|
|
*
|
|
* @param User $user
|
|
* @throws InvalidPasswordHashException
|
|
* @throws StopActionException
|
|
* @Validate("In2code\Femanager\Domain\Validator\ServersideValidator", param="user")
|
|
* @Validate("In2code\Femanager\Domain\Validator\PasswordValidator", param="user")
|
|
* @Validate("In2code\Femanager\Domain\Validator\CaptchaValidator", param="user")
|
|
*/
|
|
public function createAction(User $user)
|
|
{
|
|
if ($this->ratelimiterService->isLimited()) {
|
|
$this->addFlashMessage(
|
|
LocalizationUtility::translate('ratelimiter_too_many_attempts'),
|
|
'',
|
|
AbstractMessage::ERROR
|
|
);
|
|
$this->redirect('createStatus');
|
|
}
|
|
$user = UserUtility::overrideUserGroup($user, $this->settings);
|
|
$configuration = ConfigurationUtility::getValue('new./forceValues./beforeAnyConfirmation.', $this->config);
|
|
$user = FrontendUtility::forceValues($user, $configuration);
|
|
$user = UserUtility::fallbackUsernameAndPassword($user);
|
|
$user = UserUtility::takeEmailAsUsername($user, $this->settings);
|
|
|
|
UserUtility::hashPassword($user, ConfigurationUtility::getValue('new/misc/passwordSave', $this->settings));
|
|
|
|
$this->eventDispatcher->dispatch(new BeforeUserCreateEvent($user));
|
|
$this->ratelimiterService->consumeSlot();
|
|
|
|
if ($this->isAllConfirmed()) {
|
|
$this->createAllConfirmed($user);
|
|
} else {
|
|
$this->createRequest($user);
|
|
}
|
|
|
|
$this->redirect('createStatus');
|
|
}
|
|
|
|
/**
|
|
* Dispatcher action for every confirmation request
|
|
*
|
|
* @param int $user User UID (user could be hidden)
|
|
* @param string $hash Given hash
|
|
* @param string $status
|
|
* "userConfirmation", "userConfirmationRefused", "adminConfirmation",
|
|
* "adminConfirmationRefused", "adminConfirmationRefusedSilent"
|
|
* @param string $adminHash
|
|
* @throws IllegalObjectTypeException
|
|
* @throws StopActionException
|
|
*/
|
|
public function confirmCreateRequestAction(int $user, string $hash, string $status = 'adminConfirmation', string $adminHash = null)
|
|
{
|
|
$backend = false;
|
|
$furtherFunctions = false;
|
|
|
|
$user = $this->userRepository->findByUid($user);
|
|
|
|
$this->eventDispatcher->dispatch(new BeforeUserConfirmEvent($user, $hash, $status));
|
|
|
|
if ($user === null) {
|
|
$this->addFlashMessage(LocalizationUtility::translate('missingUserInDatabase'), '', AbstractMessage::ERROR);
|
|
$this->redirect('new');
|
|
}
|
|
|
|
$request = ServerRequestFactory::fromGlobals();
|
|
// check if the the request was triggered via Backend
|
|
if ($request->hasHeader('Accept')) {
|
|
$accept = $request->getHeader('Accept')[0];
|
|
if (false !== strpos($accept, 'application/json')) {
|
|
$backend = true;
|
|
}
|
|
}
|
|
|
|
switch ($status) {
|
|
case 'userConfirmation':
|
|
if ($status === 'userConfirmation' && ConfigurationUtility::getValue(
|
|
'new./email./createUserConfirmation./confirmUserConfirmation',
|
|
$this->config
|
|
) == '1') {
|
|
$this->view->assignMultiple(
|
|
[
|
|
'user' => $user,
|
|
'status' => 'confirmUser',
|
|
'hash' => $hash,
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
$furtherFunctions = $this->statusUserConfirmation($user, $hash, $status);
|
|
break;
|
|
|
|
case 'confirmDeletion':
|
|
$furtherFunctions = $this->statusUserConfirmationRefused($user, $hash);
|
|
break;
|
|
|
|
case 'confirmedByUser':
|
|
$furtherFunctions = $this->statusUserConfirmation($user, $hash, $status);
|
|
break;
|
|
|
|
case 'userConfirmationRefused':
|
|
if (ConfigurationUtility::getValue('new./email./createUserConfirmation./confirmUserConfirmationRefused', $this->config) == '1') {
|
|
$this->view->assignMultiple(
|
|
[
|
|
'user' => $user,
|
|
'status' => 'confirmDeletion',
|
|
'hash' =>$hash
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
$furtherFunctions = $this->statusUserConfirmationRefused($user, $hash);
|
|
break;
|
|
|
|
case 'adminConfirmation':
|
|
if ($status === 'adminConfirmation' && ConfigurationUtility::getValue(
|
|
'new./email./createUserConfirmation./confirmAdminConfirmation',
|
|
$this->config
|
|
) == '1') {
|
|
|
|
if (!HashUtility::validHash($adminHash, $user, 'admin')) {
|
|
$this->addFlashMessage(
|
|
LocalizationUtility::translate('error_not_authorized'),
|
|
'',
|
|
ContextualFeedbackSeverity::ERROR
|
|
);
|
|
throw new PropagateResponseException($this->redirect('new'), 1743766811);
|
|
}
|
|
|
|
$this->view->assignMultiple(
|
|
[
|
|
'user' => $user,
|
|
'status' => 'confirmAdmin',
|
|
'hash' => $hash,
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
|
|
if (($status === 'adminConfirmationRefused' || $status === 'adminConfirmationRefusedSilent') &&
|
|
ConfigurationUtility::getValue(
|
|
'new./email./createUserConfirmation./confirmAdminConfirmation',
|
|
$this->config
|
|
) == '1') {
|
|
|
|
if (!HashUtility::validHash($adminHash, $user, 'admin')) {
|
|
$this->addFlashMessage(
|
|
LocalizationUtility::translate('error_not_authorized'),
|
|
'',
|
|
ContextualFeedbackSeverity::ERROR
|
|
);
|
|
throw new PropagateResponseException($this->redirect('new'), 1743766811);
|
|
}
|
|
|
|
$this->view->assignMultiple(
|
|
[
|
|
'user' => $user,
|
|
'status' => 'confirmAdminRefused',
|
|
'silent' => $status === 'adminConfirmationRefusedSilent',
|
|
'hash' => $hash,
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
|
|
$furtherFunctions = $this->statusAdminConfirmation($user, $hash, $status, $backend);
|
|
break;
|
|
|
|
case 'confirmedByAdmin':
|
|
$furtherFunctions = $this->statusAdminConfirmation($user, $hash, $status, $backend);
|
|
break;
|
|
|
|
case 'confirmedByAdminRefused':
|
|
$furtherFunctions = $this->statusAdminConfirmationRefused($user, $hash, $status, $backend);
|
|
break;
|
|
|
|
case 'adminConfirmationRefused':
|
|
// Admin refuses profile
|
|
if (ConfigurationUtility::getValue(
|
|
'new./email./createUserConfirmation./confirmAdminConfirmation',
|
|
$this->config
|
|
) == '1') {
|
|
$this->view->assignMultiple(
|
|
[
|
|
'user' => $user,
|
|
'status' => 'confirmAdminRefused',
|
|
'hash' => $hash,
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
break;
|
|
|
|
case 'adminConfirmationRefusedSilent':
|
|
// Admin refuses profile
|
|
if (ConfigurationUtility::getValue(
|
|
'new./email./createUserConfirmation./confirmAdminConfirmation',
|
|
$this->config
|
|
) == '1') {
|
|
$this->view->assignMultiple(
|
|
[
|
|
'user' => $user,
|
|
'status' => 'confirmAdminRefused',
|
|
'hash' => $hash,
|
|
]
|
|
);
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
$furtherFunctions = $this->statusAdminConfirmationRefused($user, $hash, $status);
|
|
break;
|
|
case 'confirmedByAdminRefusedSilent':
|
|
$furtherFunctions = $this->statusAdminConfirmationRefused($user, $hash, $status);
|
|
break;
|
|
|
|
default:
|
|
$furtherFunctions = false;
|
|
}
|
|
|
|
if ($backend) {
|
|
$this->eventDispatcher->dispatch(new AfterRequestDispatchedEvent($this->request, $this->response));
|
|
$this->persistenceManager->persistAll();
|
|
// this request was triggered via Backend Module "Frontend users", so we stop here and provide a feedback to the BE
|
|
echo json_encode(['status' => 'okay']) . PHP_EOL;
|
|
die();
|
|
}
|
|
|
|
if ($furtherFunctions) {
|
|
$this->redirectByAction('new', $status . 'Redirect');
|
|
}
|
|
|
|
$this->redirect('new');
|
|
}
|
|
|
|
/**
|
|
* Status action: User confirmation
|
|
*
|
|
* @param User $user
|
|
* @param string $hash
|
|
* @param string $status
|
|
* @return bool allow further functions
|
|
* @throws UnsupportedRequestTypeException
|
|
* @throws IllegalObjectTypeException
|
|
*/
|
|
protected function statusUserConfirmation(User $user, string $hash, string $status)
|
|
{
|
|
if (HashUtility::validHash($hash, $user)) {
|
|
if ($user->getTxFemanagerConfirmedbyuser()) {
|
|
$this->addFlashMessage(LocalizationUtility::translate('userAlreadyConfirmed'), '', AbstractMessage::ERROR);
|
|
$this->redirect('new');
|
|
}
|
|
|
|
$user = FrontendUtility::forceValues($user, ConfigurationUtility::getValue('new./forceValues./onUserConfirmation.', $this->config));
|
|
$user->setTxFemanagerConfirmedbyuser(true);
|
|
$this->userRepository->update($user);
|
|
$this->persistenceManager->persistAll();
|
|
$this->logUtility->log(Log::STATUS_REGISTRATIONCONFIRMEDUSER, $user);
|
|
|
|
if ($this->isAdminConfirmationMissing($user)) {
|
|
$this->createAdminConfirmationRequest($user);
|
|
} else {
|
|
$user->setDisable(false);
|
|
$this->logUtility->log(Log::STATUS_NEWREGISTRATION, $user);
|
|
$this->finalCreate($user, 'new', 'createStatus', true, $status);
|
|
}
|
|
} else {
|
|
$this->addFlashMessage(LocalizationUtility::translate('createFailedProfile'), '', AbstractMessage::ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Status action: User confirmation refused
|
|
*
|
|
* @param User $user
|
|
* @param string $hash
|
|
* @return bool allow further functions
|
|
* @throws IllegalObjectTypeException
|
|
*/
|
|
protected function statusUserConfirmationRefused(User $user, $hash)
|
|
{
|
|
if (HashUtility::validHash($hash, $user)) {
|
|
$this->logUtility->log(Log::STATUS_REGISTRATIONREFUSEDUSER, $user);
|
|
$this->addFlashMessage(LocalizationUtility::translate('createProfileDeleted'));
|
|
$this->userRepository->remove($user);
|
|
} else {
|
|
$this->addFlashMessage(LocalizationUtility::translate('createFailedProfile'), '', AbstractMessage::ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Status action: Admin confirmation
|
|
*
|
|
* @param User $user
|
|
* @param string $hash
|
|
* @param string $status
|
|
* @return bool allow further functions
|
|
*/
|
|
protected function statusAdminConfirmation(User $user, $hash, $status, $backend = false)
|
|
{
|
|
if (HashUtility::validHash($hash, $user)) {
|
|
if ($user->getTxFemanagerConfirmedbyadmin()) {
|
|
$this->addFlashMessage(LocalizationUtility::translate('userAlreadyConfirmed'), '', AbstractMessage::ERROR);
|
|
$this->redirect('new');
|
|
}
|
|
|
|
$user = FrontendUtility::forceValues($user, ConfigurationUtility::getValue('new./forceValues./onAdminConfirmation.', $this->config));
|
|
$user->setTxFemanagerConfirmedbyadmin(true);
|
|
$user->setDisable(false);
|
|
$this->userRepository->update($user);
|
|
$this->logUtility->log(Log::STATUS_REGISTRATIONCONFIRMEDADMIN, $user);
|
|
$this->finalCreate($user, 'new', 'createStatus', false, $status, $backend);
|
|
} else {
|
|
$this->addFlashMessage(LocalizationUtility::translate('createFailedProfile'), '', AbstractMessage::ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Status action: Admin refused profile creation (normal or silent)
|
|
*
|
|
* @param User $user
|
|
* @param $hash
|
|
* @param $status
|
|
* @return bool allow further functions
|
|
* @throws IllegalObjectTypeException
|
|
*/
|
|
protected function statusAdminConfirmationRefused(User $user, $hash, $status)
|
|
{
|
|
if (HashUtility::validHash($hash, $user)) {
|
|
$this->logUtility->log(Log::STATUS_REGISTRATIONREFUSEDADMIN, $user);
|
|
$this->addFlashMessage(LocalizationUtility::translate('createProfileDeleted'));
|
|
if ($status !== 'adminConfirmationRefusedSilent') {
|
|
$this->sendMailService->send(
|
|
'CreateUserNotifyRefused',
|
|
StringUtility::makeEmailArray(
|
|
$user->getEmail(),
|
|
$user->getFirstName() . ' ' . $user->getLastName()
|
|
),
|
|
['sender@femanager.org' => 'Sender Name'],
|
|
'Your profile was refused',
|
|
['user' => $user],
|
|
ConfigurationUtility::getValue('new./email./createUserNotifyRefused.', $this->config)
|
|
);
|
|
}
|
|
$this->userRepository->remove($user);
|
|
} else {
|
|
$this->addFlashMessage(LocalizationUtility::translate('createFailedProfile'), '', AbstractMessage::ERROR);
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Just for showing informations after user creation
|
|
*/
|
|
public function createStatusAction(): ResponseInterface
|
|
{
|
|
$this->assignForAll();
|
|
return $this->htmlResponse();
|
|
}
|
|
|
|
/**
|
|
* Postfix method to createAction(): Create must be confirmed by Admin or User
|
|
*
|
|
* @param User $user
|
|
*/
|
|
protected function createRequest(User $user)
|
|
{
|
|
$user->setDisable(true);
|
|
$this->userRepository->add($user);
|
|
$this->persistenceManager->persistAll();
|
|
$this->logUtility->log(Log::STATUS_PROFILECREATIONREQUEST, $user);
|
|
if (!empty($this->settings['new']['confirmByUser'])) {
|
|
$this->createUserConfirmationRequest($user);
|
|
$this->redirectByAction('new', 'requestRedirect');
|
|
} elseif (!empty($this->settings['new']['confirmByAdmin'])) {
|
|
$this->createAdminConfirmationRequest($user);
|
|
$this->redirectByAction('new', 'requestRedirect');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send email to user for confirmation
|
|
*
|
|
* @param User $user
|
|
* @throws UnsupportedRequestTypeException
|
|
*/
|
|
protected function createUserConfirmationRequest(User $user)
|
|
{
|
|
$this->sendCreateUserConfirmationMail($user);
|
|
$this->addFlashMessage(LocalizationUtility::translate('createRequestWaitingForUserConfirm'));
|
|
$this->redirectByAction('new', 'requestRedirect');
|
|
}
|
|
|
|
/**
|
|
* Send email to admin for confirmation
|
|
*
|
|
* @param User $user
|
|
* @throws UnsupportedRequestTypeException
|
|
*/
|
|
protected function createAdminConfirmationRequest(User $user)
|
|
{
|
|
$aacService = $this->objectManager->get(
|
|
AutoAdminConfirmationService::class,
|
|
$user,
|
|
$this->settings,
|
|
$this->contentObject
|
|
);
|
|
if ($aacService->isAutoAdminConfirmationFullfilled()) {
|
|
$user->setDisable(false);
|
|
$this->eventDispatcher->dispatch(
|
|
new CreateConfirmationRequestEvent($user, CreateConfirmationRequestEvent::MODE_AUTOMATIC)
|
|
);
|
|
$this->createAllConfirmed($user);
|
|
} else {
|
|
$this->eventDispatcher->dispatch(
|
|
new CreateConfirmationRequestEvent($user, CreateConfirmationRequestEvent::MODE_MANUAL)
|
|
);
|
|
$this->sendMailService->send(
|
|
'createAdminConfirmation',
|
|
StringUtility::makeEmailArray(
|
|
$this->settings['new']['confirmByAdmin'] ?? '',
|
|
$this->settings['new']['email']['createAdminConfirmation']['receiver']['name']['value'] ?? ''
|
|
),
|
|
StringUtility::makeEmailArray($user->getEmail(), $user->getUsername()),
|
|
'New Registration request',
|
|
[
|
|
'user' => $user,
|
|
'hash' => HashUtility::createHashForUser($user),
|
|
'adminHash' => HashUtility::createHashForUser($user, 'admin'),
|
|
],
|
|
ConfigurationUtility::getValue('new./email./createAdminConfirmation.', $this->config)
|
|
);
|
|
$this->addFlashMessage(LocalizationUtility::translate('createRequestWaitingForAdminConfirm'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
protected function isAllConfirmed()
|
|
{
|
|
return empty($this->settings['new']['confirmByUser']) && empty($this->settings['new']['confirmByAdmin']);
|
|
}
|
|
|
|
/**
|
|
* @param User $user
|
|
* @return bool
|
|
*/
|
|
protected function isAdminConfirmationMissing(User $user)
|
|
{
|
|
return !empty($this->settings['new']['confirmByAdmin']) && !$user->getTxFemanagerConfirmedbyadmin();
|
|
}
|
|
|
|
/**
|
|
* Just for showing empty dialogue to resend confirmation mail
|
|
*/
|
|
public function resendConfirmationDialogueAction(): ResponseInterface
|
|
{
|
|
return $this->htmlResponse();
|
|
}
|
|
|
|
/**
|
|
* re-sends a confirmation email if given mail is valid
|
|
*
|
|
* @throws UnsupportedRequestTypeException
|
|
* @throws StopActionException
|
|
*/
|
|
public function resendConfirmationMailAction()
|
|
{
|
|
// @todo find a better way to fetch the data
|
|
$result = GeneralUtility::_GP('tx_femanager_pi1');
|
|
if (is_array($result)) {
|
|
if (GeneralUtility::validEmail($result['user']['email'])) {
|
|
$user = $this->userRepository->findFirstByEmail($result['user']['email']);
|
|
if (is_a($user, User::class)) {
|
|
$this->sendCreateUserConfirmationMail($user);
|
|
$this->addFlashMessage(
|
|
LocalizationUtility::translate('resendConfirmationMailSend'),
|
|
'',
|
|
AbstractMessage::INFO
|
|
);
|
|
$this->redirect('resendConfirmationDialogue');
|
|
}
|
|
}
|
|
}
|
|
$this->addFlashMessage(
|
|
LocalizationUtility::translate('resendConfirmationMailFail'),
|
|
LocalizationUtility::translate('validationError'),
|
|
AbstractMessage::ERROR
|
|
);
|
|
$this->redirect('resendConfirmationDialogue');
|
|
}
|
|
}
|