예제 #1
0
파일: PartyService.php 프로젝트: Akii/party
 /**
  * Gets the Party having an Account assigned
  *
  * @param Account $account
  * @return AbstractParty
  */
 public function getAssignedPartyOfAccount(Account $account)
 {
     $accountIdentifier = $this->persistenceManager->getIdentifierByObject($account);
     if (isset($this->accountsInPartyRuntimeCache[$accountIdentifier])) {
         return $this->accountsInPartyRuntimeCache[$accountIdentifier];
     }
     return $this->partyRepository->findOneHavingAccount($account);
 }
예제 #2
0
 /**
  * Update user preferences. The given array should contain key / value pairs of preference path => preference value
  *
  * @param array $preferences
  * @return void
  * @ExtDirect
  */
 public function updatePreferencesAction(array $preferences)
 {
     foreach ($preferences as $preferencePath => $value) {
         $this->securityContext->getParty()->getPreferences()->set($preferencePath, $value);
     }
     $this->partyRepository->update($this->securityContext->getParty());
     $this->view->setConfiguration(array('value' => array('data' => array('_descendAll' => array()))));
     $this->view->assign('value', array('data' => '', 'success' => TRUE));
 }
예제 #3
0
 /**
  * @test
  */
 public function getAssignedPartyOfAccountCachesParty()
 {
     $this->mockPersistenceManager->expects($this->any())->method('getIdentifierByObject')->will($this->returnValue('723e3913-f803-42c8-a44c-fd7115f555c3'));
     $this->mockPartyRepository->expects($this->once())->method('findOneHavingAccount')->with($this->account)->will($this->returnValue($this->party));
     $this->party->addAccount($this->account);
     $assignedParty = $this->partyService->getAssignedPartyOfAccount($this->account);
     $this->assertSame($this->party, $assignedParty);
     $assignedParty = $this->partyService->getAssignedPartyOfAccount($this->account);
     $this->assertSame($this->party, $assignedParty);
 }
예제 #4
0
 /**
  * This method is called when the form of this step has been submitted
  *
  * @param array $formValues
  * @return void
  */
 public function postProcessFormValues(array $formValues)
 {
     $user = new \TYPO3\TYPO3\Domain\Model\User();
     $name = new \TYPO3\Party\Domain\Model\PersonName('', $formValues['firstName'], '', $formValues['lastName'], '', $formValues['username']);
     $user->setName($name);
     $user->getPreferences()->set('context.workspace', 'user-' . $formValues['username']);
     $this->partyRepository->add($user);
     $account = $this->accountFactory->createAccountWithPassword($formValues['username'], $formValues['password'], array('Administrator'), 'Typo3BackendProvider');
     $account->setParty($user);
     $this->accountRepository->add($account);
 }
 /**
  * @param \TYPO3\FLOW3\Security\Account $account
  * @param array $password
  * @FLOW3\Validate(argumentName="password", type="\TYPO3\TYPO3\Validation\Validator\PasswordValidator", options={ "allowEmpty"=1, "minimum"=1, "maximum"=255 })
  * @return void
  * @todo Handle validation errors for account (accountIdentifier) & check if there's another account with the same accountIdentifier when changing it
  * @todo Security
  */
 public function updateAction(\TYPO3\FLOW3\Security\Account $account, array $password = array())
 {
     $password = array_shift($password);
     if (strlen(trim(strval($password))) > 0) {
         $account->setCredentialsSource($this->hashService->hashPassword($password, 'default'));
     }
     $this->accountRepository->update($account);
     $this->partyRepository->update($account->getParty());
     $this->addFlashMessage('The user profile has been updated.');
     $this->redirect('index');
 }
 /**
  * Update/adds a user preference
  *
  * @param string $key The key of the preference to update/add
  * @param string $value The value of the preference
  * @return void
  */
 public function updateAction($key, $value)
 {
     /** @var $user User */
     $user = $this->securityContext->getPartyByType('TYPO3\\Neos\\Domain\\Model\\User');
     // TODO: This should be done in an earlier stage (TypeConverter ?)
     if (strtolower($value) === 'false') {
         $value = FALSE;
     } elseif (strtolower($value) === 'true') {
         $value = TRUE;
     }
     $user->getPreferences()->set($key, $value);
     $this->partyRepository->update($user);
     $this->throwStatus(204, 'User preferences have been updated');
 }
 /**
  * @param Account $account
  * @param NodeInterface $userStorageNode
  * @param PersonDto $person
  * @return NodeInterface|string
  */
 protected function createProfileNode(Account $account, NodeInterface $userStorageNode, PersonDto $person)
 {
     try {
         $profileNode = $this->findProfileNode($person->getEmailAddress());
         if ($profileNode === NULL) {
             $properties = ['title' => $person->getFirstName() . ' ' . $person->getLastName(), 'firstName' => $person->getFirstName(), 'lastName' => $person->getLastName(), 'address' => $person->getAddress(), 'zipCode' => $person->getZipCode(), 'city' => $person->getCity(), 'emailAddress' => $person->getEmailAddress(), 'phone' => $person->getPhone(), 'dateOfBirth' => $person->getDateOfBirth(), 'jiuJitsu' => $person->getJiuJitsu(), 'buJitsuDo' => $person->getBuJitsuDo(), 'jiuJitsuDegree' => $person->getJiuJitsuDegree(), 'buJitsuDoDegree' => $person->getBuJitsuDoDegree(), 'gender' => $person->getGender()];
             if ($person->getFirstName() && $person->getLastName()) {
                 $nodeName = $person->getFirstName() . ' ' . $person->getLastName();
             }
             $idealNodeName = Utility::renderValidNodeName(isset($nodeName) ? $nodeName : uniqid('node'));
             $idealNodeName = htmlspecialchars($idealNodeName, ENT_NOQUOTES, 'UTF-8');
             $profileNode = $this->nodeWriteRepository->createChildNode($userStorageNode, $idealNodeName, 'BuJitsuDo.Authentication:Person', $properties);
             if ($person->getImage() instanceof Image) {
                 $profileNode = $this->profileService->setImageToNode($profileNode, $person->getImage(), $person->getFirstName(), 'Profile images');
             }
         }
         $account->getParty()->getPreferences()->set('profileNodeIdentifier', $profileNode->getIdentifier());
         $this->partyRepository->update($account->getParty());
         $this->persistenceManager->persistAll();
         $this->emitPersonCreated($profileNode);
         return $profileNode;
     } catch (\Exception $exception) {
         $this->systemLogger->log('Profile node could not be created because: ' . $exception->getMessage(), LOG_CRIT);
         return $exception->getMessage();
     }
 }
 /**
  * Authenticates against a crowd instance.
  *
  * @param \TYPO3\Flow\Security\Authentication\TokenInterface $authenticationToken The token to be authenticated
  * @return void
  * @throws \TYPO3\Flow\Security\Exception\UnsupportedAuthenticationTokenException
  */
 public function authenticate(TokenInterface $authenticationToken)
 {
     if (!$authenticationToken instanceof UsernamePassword) {
         throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1217339845);
     }
     $credentials = $authenticationToken->getCredentials();
     if (is_array($credentials) && isset($credentials['username']) && isset($credentials['password'])) {
         $crowdAuthenticationResponse = $this->crowdClient->authenticate($credentials['username'], $credentials['password']);
         if ($crowdAuthenticationResponse !== NULL) {
             /** @var $account \TYPO3\Flow\Security\Account */
             $account = NULL;
             $providerName = $this->name;
             $accountRepository = $this->accountRepository;
             $this->securityContext->withoutAuthorizationChecks(function () use($credentials, $providerName, $accountRepository, &$account) {
                 $account = $accountRepository->findActiveByAccountIdentifierAndAuthenticationProviderName($credentials['username'], $providerName);
             });
             if ($account === NULL) {
                 $account = new Account();
                 $account->setAuthenticationProviderName($providerName);
                 $account->setAccountIdentifier($credentials['username']);
                 $this->accountRepository->add($account);
             }
             $authenticateRole = $this->policyService->getRole($this->options['authenticateRole']);
             if ($account->hasRole($authenticateRole) === FALSE) {
                 $account->addRole($authenticateRole);
             }
             $crowdUser = $this->partyService->getAssignedPartyOfAccount($account);
             if ($crowdUser instanceof Person) {
                 if ($crowdUser->getName()->getFirstName() !== $crowdAuthenticationResponse['first-name']) {
                     $crowdUser->getName()->setFirstName($crowdAuthenticationResponse['first-name']);
                     $this->partyRepository->update($crowdUser);
                 }
                 if ($crowdUser->getName()->getLastName() !== $crowdAuthenticationResponse['last-name']) {
                     $crowdUser->getName()->setLastName($crowdAuthenticationResponse['last-name']);
                     $this->partyRepository->update($crowdUser);
                 }
                 if ($crowdUser->getPrimaryElectronicAddress()->getIdentifier() !== $crowdAuthenticationResponse['email']) {
                     $crowdUser->getPrimaryElectronicAddress()->setIdentifier($crowdAuthenticationResponse['email']);
                     $this->partyRepository->update($crowdUser);
                 }
             } else {
                 $crowdUser = new Person();
                 $crowdUser->setName(new PersonName('', $crowdAuthenticationResponse['first-name'], '', $crowdAuthenticationResponse['last-name']));
                 $email = new ElectronicAddress();
                 $email->setIdentifier($crowdAuthenticationResponse['email']);
                 $email->setType(ElectronicAddress::TYPE_EMAIL);
                 $crowdUser->setPrimaryElectronicAddress($email);
                 $this->partyRepository->add($crowdUser);
                 $this->partyService->assignAccountToParty($account, $crowdUser);
             }
             $authenticationToken->setAuthenticationStatus(TokenInterface::AUTHENTICATION_SUCCESSFUL);
             $authenticationToken->setAccount($account);
         } else {
             $authenticationToken->setAuthenticationStatus(TokenInterface::WRONG_CREDENTIALS);
         }
     } elseif ($authenticationToken->getAuthenticationStatus() !== TokenInterface::AUTHENTICATION_SUCCESSFUL) {
         $authenticationToken->setAuthenticationStatus(TokenInterface::NO_CREDENTIALS_GIVEN);
     }
 }
예제 #9
0
 /**
  * Persists new Account.
  *
  * @param Account $account
  *
  * @return void
  */
 public function finalizePersistingNewUser(Account $account)
 {
     $party = $account->getParty();
     if ($party instanceof AbstractParty) {
         $this->partyRepository->add($party);
     }
     $this->accountRepository->add($account);
     $this->persistenceManager->persistAll();
 }
 /**
  * Create a new user
  *
  * This command creates a new user which has access to the backend user interface.
  * It is recommended to user the email address as a username.
  *
  * @param string $username The username of the user to be created.
  * @param string $password Password of the user to be created
  * @param string $firstName First name of the user to be created
  * @param string $lastName Last name of the user to be created
  * @param string $roles A comma separated list of roles to assign
  * @FLOW3\Validate(argumentName="username", type="EmailAddress")
  * @return void
  */
 public function createCommand($username, $password, $firstName, $lastName, $roles = NULL)
 {
     $account = $this->accountRepository->findByAccountIdentifierAndAuthenticationProviderName($username, 'Typo3BackendProvider');
     if ($account instanceof \TYPO3\FLOW3\Security\Account) {
         $this->outputLine('User "%s" already exists.', array($username));
         $this->quit(1);
     }
     $user = new \TYPO3\TYPO3\Domain\Model\User();
     $name = new \TYPO3\Party\Domain\Model\PersonName('', $firstName, '', $lastName, '', $username);
     $user->setName($name);
     $workspaceName = 'user-' . preg_replace('/[^a-z0-9]/i', '', $username);
     $user->getPreferences()->set('context.workspace', $workspaceName);
     $this->partyRepository->add($user);
     $roles = empty($roles) ? array('Editor') : explode(',', $roles);
     $account = $this->accountFactory->createAccountWithPassword($username, $password, $roles, 'Typo3BackendProvider');
     $account->setParty($user);
     $this->accountRepository->add($account);
     $this->outputLine('Created account "%s".', array($username));
 }
예제 #11
0
 /**
  * @dataProvider personsDataProvider
  * @test
  */
 public function personsAndAccountPersistingAndRetrievingWorksCorrectly($firstName, $middleName, $lastName, $emailAddress)
 {
     $person = new Domain\Model\Person();
     $person->setName(new Domain\Model\PersonName('', $firstName, $middleName, $lastName));
     $electronicAddress = new Domain\Model\ElectronicAddress();
     $electronicAddress->setType(Domain\Model\ElectronicAddress::TYPE_EMAIL);
     $electronicAddress->setIdentifier($emailAddress);
     $person->setPrimaryElectronicAddress($electronicAddress);
     $account = $this->accountFactory->createAccountWithPassword($emailAddress, $this->persistenceManager->getIdentifierByObject($person));
     $this->accountRepository->add($account);
     $person->addAccount($account);
     $this->partyRepository->add($person);
     $this->persistenceManager->persistAll();
     $this->assertEquals(1, $this->partyRepository->countAll());
     $this->persistenceManager->clearState();
     $foundPerson = $this->partyRepository->findByIdentifier($this->persistenceManager->getIdentifierByObject($person));
     $this->assertEquals($foundPerson->getName()->getFullName(), $person->getName()->getFullName());
     $this->assertEquals($foundPerson->getName()->getFullName(), $firstName . ' ' . $middleName . ' ' . $lastName);
     $this->assertEquals($foundPerson->getPrimaryElectronicAddress()->getIdentifier(), $emailAddress);
 }
 /**
  * Creates a temporary account
  *
  * @param string $accountIdentifier
  * @param string $password
  * @param string $firstName
  * @param string $lastName
  * @return Account
  */
 protected function createTemporaryAccount($accountIdentifier, $password, $firstName, $lastName)
 {
     if (strlen($firstName) === 0 && strlen($lastName) === 0) {
         $firstName = 'Santa';
         $lastName = 'Claus';
     }
     $user = new User();
     $user->setName(new PersonName('', $firstName, '', $lastName));
     $user->getPreferences()->set('context.workspace', 'user-' . $accountIdentifier);
     $this->partyRepository->add($user);
     $account = $this->accountFactory->createAccountWithPassword($accountIdentifier, $password, array('TYPO3.Neos:Editor'), 'Typo3BackendProvider');
     $account->setParty($user);
     $account->setExpirationDate(new \DateTime('+1 week'));
     $this->accountRepository->add($account);
 }
 /**
  * @param Account $account
  * @param array $userdata
  * @return \TYPO3\Flow\Security\Account
  */
 protected function updateAccount(Account $account, array $userdata)
 {
     $person = $this->partyService->getAssignedPartyOfAccount($account);
     if ($person === null) {
         $person = new Person();
         $this->partyRepository->add($person);
         $this->partyService->assignAccountToParty($account, $person);
     }
     if (!$account->getRoles()) {
         $account->setRoles(array($this->policyService->getRole('T3DD.Backend:Authenticated')));
     }
     $this->updatePerson($person, $userdata);
     $this->accountRepository->update($account);
     $this->persistenceManager->persistAll();
     return $account;
 }
예제 #14
0
 /**
  * @param AbstractClientToken $token
  * @throws InvalidPartyDataException
  */
 public function createPartyAndAttachToAccountFor(AbstractClientToken $token)
 {
     $userData = $this->authenticationServicesUserData[(string) $token];
     $party = new Person();
     $party->setName(new PersonName('', $userData['first_name'], '', $userData['last_name']));
     // Todo: this is not covered by the Person implementation, we should have a solution for that
     #$party->setBirthDate(\DateTime::createFromFormat('!m/d/Y', $userData['birthday'], new \DateTimeZone('UTC')));
     #$party->setGender(substr($userData['gender'], 0, 1));
     $electronicAddress = new ElectronicAddress();
     $electronicAddress->setType(ElectronicAddress::TYPE_EMAIL);
     $electronicAddress->setIdentifier($userData['email']);
     $party->addElectronicAddress($electronicAddress);
     $partyValidator = $this->validatorResolver->getBaseValidatorConjunction('TYPO3\\Party\\Domain\\Model\\Person');
     $validationResult = $partyValidator->validate($party);
     if ($validationResult->hasErrors()) {
         throw new InvalidPartyDataException('The created party does not satisfy the requirements', 1384266207);
     }
     $account = $token->getAccount();
     $account->setParty($party);
     // TODO: this must be properly specifiable (the Roles to add)
     #$account->setRoles();
     $this->accountRepository->update($account);
     $this->partyRepository->add($party);
 }
 /**
  * Updates the given user in the respective repository and potentially executes further actions depending on what
  * has been changed.
  *
  * Note: changes to the user's account will not be committed for persistence. Please use addRoleToAccount(), removeRoleFromAccount(),
  * setRolesForAccount() and setUserPassword() for changing account properties.
  *
  * @param User $user The modified user
  * @return void
  * @api
  */
 public function updateUser(User $user)
 {
     $this->partyRepository->update($user);
     $this->emitUserUpdated($user);
 }
 /**
  * Executes this finisher
  * @see AbstractFinisher::execute()
  *
  * @return void
  * @throws \TYPO3\Flow\Mvc\Exception\StopActionException();
  */
 protected function executeInternal()
 {
     /** @var \TYPO3\Form\Core\Runtime\FormRuntime $formRuntime */
     $formRuntime = $this->finisherContext->getFormRuntime();
     $formValueArray = $formRuntime->getFormState()->getFormValues();
     if ($formRuntime->getRequest()->getParentRequest()->getControllerActionName() == 'editDataSheet') {
         // we need to update the data sheet, we assume that the person is authenticated because a data sheet can only be edited by a authenticated user
         /** @var \GIB\GradingTool\Domain\Model\Project $project */
         $project = $this->projectRepository->findByIdentifier($formRuntime->getRequest()->getParentRequest()->getArgument('project'));
         // make a HTML representation of a diff of the old and new data
         $diffContent = DiffUtility::arrayDiffRecursive($project->getDataSheetContentArray(), $formValueArray);
         // store changes to project
         $project->setDataSheetContent($formValueArray);
         $project->setLastUpdated(new \TYPO3\Flow\Utility\Now());
         // update e-mail address (could have changed in the data sheet)
         $projectManagerElectronicAddress = new \TYPO3\Party\Domain\Model\ElectronicAddress();
         $projectManagerElectronicAddress->setIdentifier($formValueArray['projectManagerEmail']);
         $projectManagerElectronicAddress->setType(\TYPO3\Party\Domain\Model\ElectronicAddress::TYPE_EMAIL);
         $project->getProjectManager()->setPrimaryElectronicAddress($projectManagerElectronicAddress);
         $this->partyRepository->update($project->getProjectManager());
         $this->projectRepository->update($project);
         $this->persistenceManager->persistAll();
         // send a notification mail to the Administrator containing the changes
         $templateIdentifierOverlay = $this->templateService->getTemplateIdentifierOverlay('editDataSheetNotification', $project);
         $this->notificationMailService->sendNotificationMail($templateIdentifierOverlay, $project, NULL, '', '', $diffContent);
         // add a flash message
         $message = new \TYPO3\Flow\Error\Message('Your data sheet for project "%s" was successfully edited.', \TYPO3\Flow\Error\Message::SEVERITY_OK, array($project->getProjectTitle()));
         $this->flashMessageContainer->addMessage($message);
     } else {
         // we need to add a new data sheet
         /** @var \GIB\GradingTool\Domain\Model\Project $project */
         $project = new \GIB\GradingTool\Domain\Model\Project();
         $project->setProjectTitle($formValueArray['projectTitle']);
         $project->setDataSheetFormIdentifier($this->settings['forms']['dataSheet']['default']);
         $project->setSubmissionFormIdentifier($this->settings['forms']['submission']['default']);
         // store identifier=userName and password for later usage
         $identifier = $formValueArray['userName'];
         $password = $formValueArray['password'];
         // remove userName and password from data array so it doesn't get saved unencrypted
         unset($formValueArray['userName']);
         unset($formValueArray['password']);
         $project->setDataSheetContent($formValueArray);
         $project->setCreated(new \TYPO3\Flow\Utility\Now());
         $this->projectRepository->add($project);
         // add a flash message
         $message = new \TYPO3\Flow\Error\Message('Your data sheet for project "%s" was successfully submitted.', \TYPO3\Flow\Error\Message::SEVERITY_OK, array($formValueArray['projectTitle']));
         $this->flashMessageContainer->addMessage($message);
         if (!$this->authenticationManager->isAuthenticated() || $this->authenticationManager->isAuthenticated() && $this->authenticationManager->getSecurityContext()->hasRole('GIB.GradingTool:Administrator')) {
             // the product manager (supposedly) doesn't have an account yet, so we create one
             $projectManager = new \GIB\GradingTool\Domain\Model\ProjectManager();
             $projectManagerName = new \TYPO3\Party\Domain\Model\PersonName('', $formValueArray['projectManagerFirstName'], '', $formValueArray['projectManagerLastName']);
             $projectManager->setName($projectManagerName);
             $projectManagerElectronicAddress = new \TYPO3\Party\Domain\Model\ElectronicAddress();
             $projectManagerElectronicAddress->setIdentifier($formValueArray['projectManagerEmail']);
             $projectManagerElectronicAddress->setType(\TYPO3\Party\Domain\Model\ElectronicAddress::TYPE_EMAIL);
             $projectManager->addElectronicAddress($projectManagerElectronicAddress);
             $projectManager->setPrimaryElectronicAddress($projectManagerElectronicAddress);
             // add account
             $roles = array('GIB.GradingTool:ProjectManager');
             $authenticationProviderName = 'DefaultProvider';
             $account = $this->accountFactory->createAccountWithPassword($identifier, $password, $roles, $authenticationProviderName);
             $this->accountRepository->add($account);
             // add account to ProjectManager
             $projectManager->addAccount($account);
             // add project to ProjectManager
             $projectManager->addProject($project);
             // finally add the complete ProjectManager
             $this->partyRepository->add($projectManager);
             if (!$this->authenticationManager->getSecurityContext()->hasRole('GIB.GradingTool:Administrator')) {
                 // authenticate user if no Administrator is authenticated
                 $authenticationTokens = $this->securityContext->getAuthenticationTokensOfType('TYPO3\\Flow\\Security\\Authentication\\Token\\UsernamePassword');
                 if (count($authenticationTokens) === 1) {
                     $authenticationTokens[0]->setAccount($account);
                     $authenticationTokens[0]->setAuthenticationStatus(\TYPO3\Flow\Security\Authentication\TokenInterface::AUTHENTICATION_SUCCESSFUL);
                 }
                 // add a flash message
                 $message = new \TYPO3\Flow\Error\Message('The account "%s" was created and you were successfully logged in.', \TYPO3\Flow\Error\Message::SEVERITY_OK, array($identifier));
                 $this->flashMessageContainer->addMessage($message);
             }
         } elseif ($this->authenticationManager->isAuthenticated() && $this->authenticationManager->getSecurityContext()->hasRole('GIB.GradingTool:ProjectManager')) {
             // a productManager is adding a new project to his account
             /** @var \GIB\GradingTool\Domain\Model\ProjectManager $projectManager */
             $projectManager = $this->authenticationManager->getSecurityContext()->getParty();
             $projectManager->addProject($project);
             $this->partyRepository->update($projectManager);
         }
         $this->persistenceManager->persistAll();
         // send notification mail to project manager (bcc to team)
         $templateIdentifierOverlay = $this->templateService->getTemplateIdentifierOverlay('newDataSheetProjectManagerNotification', $project);
         $this->notificationMailService->sendNotificationMail($templateIdentifierOverlay, $project, $projectManager, $formValueArray['projectManagerFirstName'] . ' ' . $formValueArray['projectManagerLastName'], $formValueArray['projectManagerEmail']);
         // send notification mail to the GIB team
         $templateIdentifierOverlay = $this->templateService->getTemplateIdentifierOverlay('newDataSheetTeamNotification', $project);
         $dataSheetArray = $this->dataSheetService->getProcessedDataSheet($project);
         $this->notificationMailService->sendNotificationMail($templateIdentifierOverlay, $project, $projectManager, '', '', $dataSheetArray);
     }
     $this->persistenceManager->persistAll();
     // redirect to dashboard
     $formRuntime = $this->finisherContext->getFormRuntime();
     $request = $formRuntime->getRequest()->getMainRequest();
     $uriBuilder = new \TYPO3\Flow\Mvc\Routing\UriBuilder();
     $uriBuilder->setRequest($request);
     $uriBuilder->reset();
     $uri = $uriBuilder->uriFor('editDatasheet', array('project' => $project), 'Project');
     $response = $formRuntime->getResponse();
     $mainResponse = $response;
     while ($response = $response->getParentResponse()) {
         $mainResponse = $response;
     }
     $mainResponse->setStatus(303);
     $mainResponse->setHeader('Location', (string) $uri);
     throw new \TYPO3\Flow\Mvc\Exception\StopActionException();
 }