Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\UserBundle\Model;
|
||||
|
||||
use Mautic\UserBundle\Event\PasswordStrengthValidateEvent;
|
||||
use Mautic\UserBundle\UserEvents;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use ZxcvbnPhp\Zxcvbn as PasswordStrengthEstimator;
|
||||
|
||||
class PasswordStrengthEstimatorModel
|
||||
{
|
||||
public const MINIMUM_PASSWORD_STRENGTH_ALLOWED = 3;
|
||||
|
||||
private const DICTIONARY = [
|
||||
'mautic',
|
||||
'user',
|
||||
'lead',
|
||||
'bundle',
|
||||
'campaign',
|
||||
'company',
|
||||
];
|
||||
|
||||
private PasswordStrengthEstimator $passwordStrengthEstimator;
|
||||
|
||||
public function __construct(private EventDispatcherInterface $dispatcher)
|
||||
{
|
||||
$this->passwordStrengthEstimator = new PasswordStrengthEstimator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $dictionary
|
||||
*/
|
||||
public function validate(?string $password, int $score = self::MINIMUM_PASSWORD_STRENGTH_ALLOWED, array $dictionary = self::DICTIONARY): bool
|
||||
{
|
||||
$isValid = $score <= $this->passwordStrengthEstimator->passwordStrength($password, $this->sanitizeDictionary($dictionary))['score'];
|
||||
|
||||
$passwordStrengthValidateEvent = new PasswordStrengthValidateEvent($isValid, $password);
|
||||
$this->dispatcher->dispatch($passwordStrengthValidateEvent, UserEvents::USER_PASSWORD_STRENGTH_VALIDATION);
|
||||
|
||||
return $passwordStrengthValidateEvent->isValid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $dictionary
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function sanitizeDictionary(array $dictionary): array
|
||||
{
|
||||
return array_unique(array_filter($dictionary));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Model;
|
||||
|
||||
use Mautic\CoreBundle\Model\FormModel;
|
||||
use Mautic\CoreBundle\Model\GlobalSearchInterface;
|
||||
use Mautic\UserBundle\Entity\Role;
|
||||
use Mautic\UserBundle\Entity\RoleRepository;
|
||||
use Mautic\UserBundle\Event\RoleEvent;
|
||||
use Mautic\UserBundle\Form\Type\RoleType;
|
||||
use Mautic\UserBundle\UserEvents;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* @extends FormModel<Role>
|
||||
*/
|
||||
class RoleModel extends FormModel implements GlobalSearchInterface
|
||||
{
|
||||
public function getRepository(): RoleRepository
|
||||
{
|
||||
return $this->em->getRepository(Role::class);
|
||||
}
|
||||
|
||||
public function getPermissionBase(): string
|
||||
{
|
||||
return 'user:roles';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MethodNotAllowedHttpException
|
||||
*/
|
||||
public function saveEntity($entity, $unlock = true): void
|
||||
{
|
||||
if (!$entity instanceof Role) {
|
||||
throw new MethodNotAllowedHttpException(['Role'], 'Entity must be of class Role()');
|
||||
}
|
||||
|
||||
$isNew = ($entity->getId()) ? 0 : 1;
|
||||
|
||||
if (!$isNew) {
|
||||
// delete all existing
|
||||
$this->em->getRepository(\Mautic\UserBundle\Entity\Permission::class)->purgeRolePermissions($entity);
|
||||
}
|
||||
|
||||
parent::saveEntity($entity, $unlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the role's permissions.
|
||||
*
|
||||
* @param array $rawPermissions (i.e. from request)
|
||||
*/
|
||||
public function setRolePermissions(Role &$entity, $rawPermissions): void
|
||||
{
|
||||
if (!is_array($rawPermissions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set permissions if applicable and if the user is not an admin
|
||||
$permissions = (!$entity->isAdmin() && !empty($rawPermissions)) ?
|
||||
$this->security->generatePermissions($rawPermissions) :
|
||||
[];
|
||||
|
||||
foreach ($permissions as $permissionEntity) {
|
||||
$entity->addPermission($permissionEntity);
|
||||
}
|
||||
|
||||
$entity->setRawPermissions($rawPermissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws PreconditionRequiredHttpException
|
||||
*/
|
||||
public function deleteEntity($entity): void
|
||||
{
|
||||
if (!$entity instanceof Role) {
|
||||
throw new MethodNotAllowedHttpException(['Role'], 'Entity must be of class Role()');
|
||||
}
|
||||
|
||||
$users = $this->em->getRepository(\Mautic\UserBundle\Entity\User::class)->findByRole($entity);
|
||||
if (count($users)) {
|
||||
throw new PreconditionRequiredHttpException($this->translator->trans('mautic.user.role.error.deletenotallowed', ['%name%' => $entity->getName()], 'flashes'));
|
||||
}
|
||||
|
||||
parent::deleteEntity($entity);
|
||||
}
|
||||
|
||||
public function createForm($entity, FormFactoryInterface $formFactory, $action = null, $options = []): \Symfony\Component\Form\FormInterface
|
||||
{
|
||||
if (!$entity instanceof Role) {
|
||||
throw new MethodNotAllowedHttpException(['Role']);
|
||||
}
|
||||
|
||||
if (!empty($action)) {
|
||||
$options['action'] = $action;
|
||||
}
|
||||
|
||||
return $formFactory->create(RoleType::class, $entity, $options);
|
||||
}
|
||||
|
||||
public function getEntity($id = null): ?Role
|
||||
{
|
||||
if (null === $id) {
|
||||
return new Role();
|
||||
}
|
||||
|
||||
return parent::getEntity($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MethodNotAllowedHttpException
|
||||
*/
|
||||
protected function dispatchEvent($action, &$entity, $isNew = false, ?Event $event = null): ?Event
|
||||
{
|
||||
if (!$entity instanceof Role) {
|
||||
throw new MethodNotAllowedHttpException(['Role'], 'Entity must be of class Role()');
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'pre_save':
|
||||
$name = UserEvents::ROLE_PRE_SAVE;
|
||||
break;
|
||||
case 'post_save':
|
||||
$name = UserEvents::ROLE_POST_SAVE;
|
||||
break;
|
||||
case 'pre_delete':
|
||||
$name = UserEvents::ROLE_PRE_DELETE;
|
||||
break;
|
||||
case 'post_delete':
|
||||
$name = UserEvents::ROLE_POST_DELETE;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->dispatcher->hasListeners($name)) {
|
||||
if (empty($event)) {
|
||||
$event = new RoleEvent($entity, $isNew);
|
||||
$event->setEntityManager($this->em);
|
||||
}
|
||||
$this->dispatcher->dispatch($event, $name);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Model;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Model\FormModel;
|
||||
use Mautic\CoreBundle\Model\GlobalSearchInterface;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\EmailBundle\Helper\MailHelper;
|
||||
use Mautic\UserBundle\Entity\Role;
|
||||
use Mautic\UserBundle\Entity\User;
|
||||
use Mautic\UserBundle\Entity\UserRepository;
|
||||
use Mautic\UserBundle\Entity\UserToken;
|
||||
use Mautic\UserBundle\Enum\UserTokenAuthorizator;
|
||||
use Mautic\UserBundle\Event\UserEvent;
|
||||
use Mautic\UserBundle\Form\Type\UserType;
|
||||
use Mautic\UserBundle\Model\UserToken\UserTokenServiceInterface;
|
||||
use Mautic\UserBundle\UserEvents;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasher;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* @extends FormModel<User>
|
||||
*/
|
||||
class UserModel extends FormModel implements GlobalSearchInterface
|
||||
{
|
||||
public function __construct(
|
||||
protected MailHelper $mailHelper,
|
||||
private UserTokenServiceInterface $userTokenService,
|
||||
EntityManager $em,
|
||||
CorePermissions $security,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
UrlGeneratorInterface $router,
|
||||
Translator $translator,
|
||||
UserHelper $userHelper,
|
||||
LoggerInterface $mauticLogger,
|
||||
CoreParametersHelper $coreParametersHelper,
|
||||
) {
|
||||
parent::__construct($em, $security, $dispatcher, $router, $translator, $userHelper, $mauticLogger, $coreParametersHelper);
|
||||
}
|
||||
|
||||
public function getRepository(): UserRepository
|
||||
{
|
||||
return $this->em->getRepository(User::class);
|
||||
}
|
||||
|
||||
public function getPermissionBase(): string
|
||||
{
|
||||
return 'user:users';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MethodNotAllowedHttpException
|
||||
*/
|
||||
public function saveEntity($entity, $unlock = true): void
|
||||
{
|
||||
if (!$entity instanceof User) {
|
||||
throw new MethodNotAllowedHttpException(['User'], 'Entity must be of class User()');
|
||||
}
|
||||
|
||||
parent::saveEntity($entity, $unlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of users for an autocomplete input.
|
||||
*
|
||||
* @param string $search
|
||||
* @param int $limit
|
||||
* @param int $start
|
||||
* @param array $permissionLimiter
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUserList($search = '', $limit = 10, $start = 0, $permissionLimiter = [])
|
||||
{
|
||||
return $this->getRepository()->getUserList($search, $limit, $start, $permissionLimiter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for a new password and rehashes if necessary.
|
||||
*
|
||||
* @param string $submittedPassword
|
||||
* @param bool|false $validate
|
||||
*/
|
||||
public function checkNewPassword(User $entity, UserPasswordHasherInterface $hasher, $submittedPassword, $validate = false): ?string
|
||||
{
|
||||
if ($validate) {
|
||||
if (strlen($submittedPassword) < 6) {
|
||||
throw new \InvalidArgumentException($this->translator->trans('mautic.user.user.password.minlength', [], 'validators'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($submittedPassword)) {
|
||||
// hash the clear password submitted via the form
|
||||
return $hasher->hashPassword($entity, $submittedPassword);
|
||||
}
|
||||
|
||||
return $entity->getPassword();
|
||||
}
|
||||
|
||||
public function createForm($entity, FormFactoryInterface $formFactory, $action = null, $options = []): \Symfony\Component\Form\FormInterface
|
||||
{
|
||||
if (!$entity instanceof User) {
|
||||
throw new MethodNotAllowedHttpException(['User'], 'Entity must be of class User()');
|
||||
}
|
||||
if (!empty($action)) {
|
||||
$options['action'] = $action;
|
||||
}
|
||||
|
||||
return $formFactory->create(UserType::class, $entity, $options);
|
||||
}
|
||||
|
||||
public function getEntity($id = null): ?User
|
||||
{
|
||||
if (null === $id) {
|
||||
return new User();
|
||||
}
|
||||
|
||||
$entity = parent::getEntity($id);
|
||||
|
||||
if ($entity) {
|
||||
// add user's permissions
|
||||
$entity->setActivePermissions(
|
||||
$this->em->getRepository(\Mautic\UserBundle\Entity\Permission::class)->getPermissionsByRole($entity->getRole())
|
||||
);
|
||||
}
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User|null
|
||||
*/
|
||||
public function getSystemAdministrator()
|
||||
{
|
||||
$adminRole = $this->em->getRepository(Role::class)->findOneBy(['isAdmin' => true]);
|
||||
|
||||
return $this->getRepository()->findOneBy(
|
||||
[
|
||||
'role' => $adminRole,
|
||||
'isPublished' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws MethodNotAllowedHttpException
|
||||
*/
|
||||
protected function dispatchEvent($action, &$entity, $isNew = false, ?Event $event = null): ?Event
|
||||
{
|
||||
if (!$entity instanceof User) {
|
||||
throw new MethodNotAllowedHttpException(['User'], 'Entity must be of class User()');
|
||||
}
|
||||
|
||||
switch ($action) {
|
||||
case 'pre_save':
|
||||
$name = UserEvents::USER_PRE_SAVE;
|
||||
break;
|
||||
case 'post_save':
|
||||
$name = UserEvents::USER_POST_SAVE;
|
||||
break;
|
||||
case 'pre_delete':
|
||||
$name = UserEvents::USER_PRE_DELETE;
|
||||
break;
|
||||
case 'post_delete':
|
||||
$name = UserEvents::USER_POST_DELETE;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->dispatcher->hasListeners($name)) {
|
||||
if (empty($event)) {
|
||||
$event = new UserEvent($entity, $isNew);
|
||||
$event->setEntityManager($this->em);
|
||||
}
|
||||
$this->dispatcher->dispatch($event, $name);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of entities for autopopulate fields.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $filter
|
||||
* @param int $limit
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLookupResults($type, $filter = '', $limit = 10)
|
||||
{
|
||||
$results = [];
|
||||
|
||||
return match ($type) {
|
||||
'role' => $this->em->getRepository(Role::class)->getRoleList($filter, $limit),
|
||||
'user' => $this->em->getRepository(User::class)->getUserList($filter, $limit),
|
||||
'position' => $this->em->getRepository(User::class)->getPositionList($filter, $limit),
|
||||
default => $results,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the user password and emails it.
|
||||
*
|
||||
* @param string $newPassword
|
||||
*/
|
||||
public function resetPassword(User $user, UserPasswordHasher $hasher, $newPassword): void
|
||||
{
|
||||
$hashedPassword = $this->checkNewPassword($user, $hasher, $newPassword);
|
||||
|
||||
$user->setPassword($hashedPassword);
|
||||
$this->saveEntity($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserToken
|
||||
*/
|
||||
protected function getResetToken(User $user)
|
||||
{
|
||||
$userToken = new UserToken();
|
||||
$userToken->setUser($user)
|
||||
->setAuthorizator(UserTokenAuthorizator::RESET_PASSWORD_AUTHORIZATOR)
|
||||
->setExpiration((new \DateTime())->add(new \DateInterval('PT24H')))
|
||||
->setOneTimeOnly();
|
||||
|
||||
return $this->userTokenService->generateSecret($userToken, 64);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function confirmResetToken(User $user, $token)
|
||||
{
|
||||
$userToken = new UserToken();
|
||||
$userToken->setUser($user)
|
||||
->setAuthorizator(UserTokenAuthorizator::RESET_PASSWORD_AUTHORIZATOR)
|
||||
->setSecret($token);
|
||||
|
||||
return $this->userTokenService->verify($userToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function sendResetEmail(User $user): void
|
||||
{
|
||||
$mailer = $this->mailHelper->getMailer();
|
||||
|
||||
$resetToken = $this->getResetToken($user);
|
||||
$this->em->persist($resetToken);
|
||||
try {
|
||||
$this->em->flush();
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->error($exception->getMessage());
|
||||
throw new \RuntimeException();
|
||||
}
|
||||
$resetLink = $this->router->generate('mautic_user_passwordresetconfirm', ['token' => $resetToken->getSecret()], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
|
||||
$mailer->setTo([$user->getEmail() => $user->getName()]);
|
||||
$mailer->setSubject($this->translator->trans('mautic.user.user.passwordreset.subject'));
|
||||
$text = $this->translator->trans(
|
||||
'mautic.user.user.passwordreset.email.body',
|
||||
['%name%' => $user->getFirstName(), '%resetlink%' => '<a href="'.$resetLink.'">'.$resetLink.'</a>']
|
||||
);
|
||||
$text = str_replace('\\n', "\n", $text);
|
||||
$html = nl2br($text);
|
||||
|
||||
$this->emailUser(
|
||||
$user,
|
||||
$this->translator->trans('mautic.user.user.passwordreset.subject'),
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function sendChangePasswordInfo(User $user): void
|
||||
{
|
||||
$text = $this->translator->trans(
|
||||
'mautic.user.user.passwordchange.email.body',
|
||||
['%name%' => $user->getFirstName()]
|
||||
);
|
||||
$text = str_replace('\\n', "\n", $text);
|
||||
$html = nl2br($text);
|
||||
|
||||
$this->emailUser(
|
||||
$user,
|
||||
$this->translator->trans('mautic.user.user.passwordchange.subject'),
|
||||
$html
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function sendChangeEmailInfo(string $oldEmail, User $user): void
|
||||
{
|
||||
$mailer = $this->mailHelper->getMailer();
|
||||
$text = $this->translator->trans(
|
||||
'mautic.user.user.emailchange.email.body',
|
||||
['%name%' => $user->getFirstName()]
|
||||
);
|
||||
$text = str_replace('\\n', "\n", $text);
|
||||
$html = nl2br($text);
|
||||
|
||||
$mailer->setTo([$oldEmail => $user->getName()]);
|
||||
$mailer->setBody($html);
|
||||
$mailer->setSubject($this->translator->trans('mautic.user.user.emailchange.subject'));
|
||||
$mailer->send();
|
||||
}
|
||||
|
||||
public function emailUser(User $user, string $subject, string $content): void
|
||||
{
|
||||
$mailer = $this->prepareEMail($subject, $content);
|
||||
$mailer->setTo([$user->getEmail() => $user->getName()]);
|
||||
$mailer->send();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $emailAddresses
|
||||
*/
|
||||
public function sendMailToEmailAddresses(array $emailAddresses, string $subject, string $content): void
|
||||
{
|
||||
$mailer = $this->prepareEMail($subject, $content);
|
||||
$mailer->setTo($emailAddresses);
|
||||
$mailer->send();
|
||||
}
|
||||
|
||||
private function prepareEMail(string $subject, string $content): MailHelper
|
||||
{
|
||||
$mailer = $this->mailHelper->getMailer();
|
||||
$content = str_replace('\\n', "\n", $content);
|
||||
$html = nl2br($content);
|
||||
$mailer->setSubject($subject);
|
||||
$mailer->setBody($html);
|
||||
$mailer->setPlainText(strip_tags($content));
|
||||
|
||||
return $mailer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user preference.
|
||||
*/
|
||||
public function setPreference($key, $value = null, ?User $user = null): void
|
||||
{
|
||||
if (null == $user) {
|
||||
$user = $this->userHelper->getUser();
|
||||
}
|
||||
|
||||
$preferences = $user->getPreferences();
|
||||
$preferences[$key] = $value;
|
||||
|
||||
$user->setPreferences($preferences);
|
||||
|
||||
$this->getRepository()->saveEntity($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user preference.
|
||||
*/
|
||||
public function getPreference($key, $default = null, ?User $user = null)
|
||||
{
|
||||
if (null == $user) {
|
||||
$user = $this->userHelper->getUser();
|
||||
}
|
||||
$preferences = $user->getPreferences();
|
||||
|
||||
return $preferences[$key] ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of Users for formType Choice.
|
||||
*/
|
||||
public function getOwnerListChoices(): array
|
||||
{
|
||||
return $this->getRepository()->getOwnerListChoices();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Model\UserToken;
|
||||
|
||||
use Mautic\CoreBundle\Helper\RandomHelper\RandomHelperInterface;
|
||||
use Mautic\UserBundle\Entity\UserToken;
|
||||
use Mautic\UserBundle\Entity\UserTokenRepositoryInterface;
|
||||
|
||||
final class UserTokenService implements UserTokenServiceInterface
|
||||
{
|
||||
public function __construct(
|
||||
private RandomHelperInterface $randomHelper,
|
||||
private UserTokenRepositoryInterface $userTokenRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $secretLength
|
||||
*
|
||||
* @return UserToken
|
||||
*/
|
||||
public function generateSecret(UserToken $token, $secretLength = 32)
|
||||
{
|
||||
do {
|
||||
$randomSecret = $this->randomHelper->generate($secretLength);
|
||||
$isSecretUnique = $this->userTokenRepository->isSecretUnique($randomSecret);
|
||||
} while (false === $isSecretUnique);
|
||||
|
||||
return $token->setSecret($randomSecret);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function verify(UserToken $token)
|
||||
{
|
||||
return $this->userTokenRepository->verify($token);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Model\UserToken;
|
||||
|
||||
use Mautic\UserBundle\Entity\UserToken;
|
||||
|
||||
/**
|
||||
* Interface UserTokenServiceInterface.
|
||||
*/
|
||||
interface UserTokenServiceInterface
|
||||
{
|
||||
/**
|
||||
* @param int $secretLength
|
||||
*
|
||||
* @return UserToken
|
||||
*/
|
||||
public function generateSecret(UserToken $token, $secretLength = 32);
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function verify(UserToken $token);
|
||||
}
|
||||
Reference in New Issue
Block a user