Spaces:
No application file
No application file
| namespace Mautic\UserBundle\Entity; | |
| use Doctrine\ORM\Mapping as ORM; | |
| use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver; | |
| use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; | |
| use Mautic\CoreBundle\Entity\CacheInvalidateInterface; | |
| use Mautic\CoreBundle\Entity\FormEntity; | |
| use Mautic\UserBundle\Form\Validator\Constraints\NotWeak; | |
| use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; | |
| use Symfony\Component\Form\Form; | |
| use Symfony\Component\Security\Core\User\EquatableInterface; | |
| use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; | |
| use Symfony\Component\Security\Core\User\UserInterface; | |
| use Symfony\Component\Validator\Constraints as Assert; | |
| use Symfony\Component\Validator\Mapping\ClassMetadata; | |
| class User extends FormEntity implements UserInterface, EquatableInterface, PasswordAuthenticatedUserInterface, CacheInvalidateInterface | |
| { | |
| public const CACHE_NAMESPACE = 'User'; | |
| /** | |
| * @var ?int | |
| */ | |
| protected $id; | |
| /** | |
| * @var string | |
| */ | |
| protected $username; | |
| /** | |
| * @var string | |
| */ | |
| protected $password; | |
| /** | |
| * Used for when updating the password. | |
| * | |
| * @var ?string | |
| */ | |
| private $plainPassword; | |
| /** | |
| * Used for updating account. | |
| * | |
| * @var ?string | |
| */ | |
| private $currentPassword; | |
| /** | |
| * @var string | |
| */ | |
| private $firstName; | |
| /** | |
| * @var string | |
| */ | |
| private $lastName; | |
| /** | |
| * @var string | |
| */ | |
| private $email; | |
| /** | |
| * @var string|null | |
| */ | |
| private $position; | |
| /** | |
| * @var Role | |
| */ | |
| private $role; | |
| /** | |
| * @var string|null | |
| */ | |
| private $timezone = ''; | |
| /** | |
| * @var string|null | |
| */ | |
| private $locale = ''; | |
| /** | |
| * @var \DateTimeInterface | |
| */ | |
| private $lastLogin; | |
| /** | |
| * @var \DateTimeInterface | |
| */ | |
| private $lastActive; | |
| /** | |
| * Stores active role permissions. | |
| */ | |
| private $activePermissions; | |
| /** | |
| * @var array | |
| */ | |
| private $preferences = []; | |
| /** | |
| * @var string|null | |
| */ | |
| private $signature; | |
| /** | |
| * @param bool $guest | |
| */ | |
| public function __construct( | |
| private $guest = false | |
| ) { | |
| } | |
| public static function loadMetadata(ORM\ClassMetadata $metadata): void | |
| { | |
| $builder = new ClassMetadataBuilder($metadata); | |
| $builder->setTable('users') | |
| ->setCustomRepositoryClass(UserRepository::class); | |
| $builder->addId(); | |
| $builder->createField('username', 'string') | |
| ->length(191) | |
| ->unique() | |
| ->build(); | |
| $builder->createField('password', 'string') | |
| ->length(64) | |
| ->build(); | |
| $builder->createField('firstName', 'string') | |
| ->columnName('first_name') | |
| ->length(191) | |
| ->build(); | |
| $builder->createField('lastName', 'string') | |
| ->columnName('last_name') | |
| ->length(191) | |
| ->build(); | |
| $builder->createField('email', 'string') | |
| ->length(191) | |
| ->unique() | |
| ->build(); | |
| $builder->createField('position', 'string') | |
| ->length(191) | |
| ->nullable() | |
| ->build(); | |
| $builder->createManyToOne('role', 'Role') | |
| ->inversedBy('users') | |
| ->cascadeMerge() | |
| ->addJoinColumn('role_id', 'id', false) | |
| ->build(); | |
| $builder->createField('timezone', 'string') | |
| ->nullable() | |
| ->build(); | |
| $builder->createField('locale', 'string') | |
| ->nullable() | |
| ->build(); | |
| $builder->createField('lastLogin', 'datetime') | |
| ->columnName('last_login') | |
| ->nullable() | |
| ->build(); | |
| $builder->createField('lastActive', 'datetime') | |
| ->columnName('last_active') | |
| ->nullable() | |
| ->build(); | |
| $builder->createField('preferences', 'array') | |
| ->nullable() | |
| ->build(); | |
| $builder->createField('signature', 'text') | |
| ->nullable() | |
| ->build(); | |
| } | |
| public static function loadValidatorMetadata(ClassMetadata $metadata): void | |
| { | |
| $metadata->addPropertyConstraint('username', new Assert\NotBlank( | |
| ['message' => 'mautic.user.user.username.notblank'] | |
| )); | |
| $metadata->addConstraint(new UniqueEntity( | |
| [ | |
| 'fields' => ['username'], | |
| 'message' => 'mautic.user.user.username.unique', | |
| 'repositoryMethod' => 'checkUniqueUsernameEmail', | |
| ] | |
| )); | |
| $metadata->addPropertyConstraint('firstName', new Assert\NotBlank( | |
| ['message' => 'mautic.user.user.firstname.notblank'] | |
| )); | |
| $metadata->addPropertyConstraint('lastName', new Assert\NotBlank( | |
| ['message' => 'mautic.user.user.lastname.notblank'] | |
| )); | |
| $metadata->addPropertyConstraint('email', new Assert\NotBlank( | |
| ['message' => 'mautic.user.user.email.valid'] | |
| )); | |
| $metadata->addPropertyConstraint('email', new Assert\Email( | |
| [ | |
| 'message' => 'mautic.user.user.email.valid', | |
| 'groups' => ['SecondPass'], | |
| ] | |
| )); | |
| $metadata->addConstraint(new UniqueEntity( | |
| [ | |
| 'fields' => ['email'], | |
| 'message' => 'mautic.user.user.email.unique', | |
| 'repositoryMethod' => 'checkUniqueUsernameEmail', | |
| ] | |
| )); | |
| $metadata->addPropertyConstraint('role', new Assert\NotBlank( | |
| ['message' => 'mautic.user.user.role.notblank'] | |
| )); | |
| $metadata->addPropertyConstraint('plainPassword', new Assert\NotBlank( | |
| [ | |
| 'message' => 'mautic.user.user.password.notblank', | |
| 'groups' => ['CheckPassword'], | |
| ] | |
| )); | |
| $metadata->addPropertyConstraint('plainPassword', new Assert\Length( | |
| [ | |
| 'min' => 6, | |
| 'minMessage' => 'mautic.user.user.password.minlength', | |
| 'groups' => ['CheckPassword'], | |
| ] | |
| )); | |
| $metadata->addPropertyConstraint('plainPassword', new NotWeak( | |
| [ | |
| 'message' => 'mautic.user.user.password.weak', | |
| 'groups' => ['CheckPassword'], | |
| ] | |
| )); | |
| $metadata->setGroupSequence(['User', 'SecondPass', 'CheckPassword']); | |
| } | |
| public static function determineValidationGroups(Form $form): array | |
| { | |
| $data = $form->getData(); | |
| $groups = ['User', 'SecondPass']; | |
| // check if creating a new user or editing an existing user and the password has been updated | |
| if ($data instanceof User && (!$data->getId() || ($data->getId() && $data->getPlainPassword()))) { | |
| $groups[] = 'CheckPassword'; | |
| } | |
| return $groups; | |
| } | |
| /** | |
| * Prepares the metadata for API usage. | |
| */ | |
| public static function loadApiMetadata(ApiMetadataDriver $metadata): void | |
| { | |
| $metadata->setGroupPrefix('user') | |
| ->addListProperties( | |
| [ | |
| 'id', | |
| 'username', | |
| 'firstName', | |
| 'lastName', | |
| ] | |
| ) | |
| ->addProperties( | |
| [ | |
| 'email', | |
| 'position', | |
| 'role', | |
| 'timezone', | |
| 'locale', | |
| 'lastLogin', | |
| 'lastActive', | |
| 'signature', | |
| ] | |
| ) | |
| ->build(); | |
| } | |
| protected function isChanged($prop, $val) | |
| { | |
| $getter = 'get'.ucfirst($prop); | |
| $current = $this->$getter(); | |
| if ('role' == $prop) { | |
| if ($current && !$val) { | |
| $this->changes['role'] = [$current->getName().' ('.$current->getId().')', $val]; | |
| } elseif (!$this->role && $val) { | |
| $this->changes['role'] = [$current, $val->getName().' ('.$val->getId().')']; | |
| } elseif ($current && $val && $current->getId() != $val->getId()) { | |
| $this->changes['role'] = [ | |
| $current->getName().'('.$current->getId().')', | |
| $val->getName().'('.$val->getId().')', | |
| ]; | |
| } | |
| } else { | |
| parent::isChanged($prop, $val); | |
| } | |
| } | |
| public function getUsername() | |
| { | |
| return $this->username; | |
| } | |
| public function getUserIdentifier(): string | |
| { | |
| return $this->username; | |
| } | |
| public function getSalt() | |
| { | |
| // bcrypt generates its own salt | |
| return null; | |
| } | |
| public function getPassword(): ?string | |
| { | |
| return $this->password; | |
| } | |
| /** | |
| * Get plain password. | |
| * | |
| * @return ?string | |
| */ | |
| public function getPlainPassword() | |
| { | |
| return $this->plainPassword; | |
| } | |
| /** | |
| * Get current password (that a user has typed into a form). | |
| * | |
| * @return ?string | |
| */ | |
| public function getCurrentPassword() | |
| { | |
| return $this->currentPassword; | |
| } | |
| public function getRoles() | |
| { | |
| $roles = []; | |
| if ($this->username) { | |
| $roles = [ | |
| ($this->isAdmin()) ? 'ROLE_ADMIN' : 'ROLE_USER', | |
| ]; | |
| if (defined('MAUTIC_API_REQUEST') && MAUTIC_API_REQUEST) { | |
| $roles[] = 'ROLE_API'; | |
| } | |
| } | |
| return $roles; | |
| } | |
| public function eraseCredentials(): void | |
| { | |
| $this->plainPassword = null; | |
| $this->currentPassword = null; | |
| } | |
| /** | |
| * @return array<int, mixed> | |
| */ | |
| public function __serialize(): array | |
| { | |
| return [ | |
| $this->id, | |
| $this->username, | |
| $this->password, | |
| $this->isPublished(), | |
| ]; | |
| } | |
| /** | |
| * @param array<int, mixed> $data | |
| */ | |
| public function __unserialize(array $data): void | |
| { | |
| [ | |
| $this->id, | |
| $this->username, | |
| $this->password, | |
| $published | |
| ] = $data; | |
| $this->setIsPublished($published); | |
| } | |
| /** | |
| * @return ?int | |
| */ | |
| public function getId() | |
| { | |
| return $this->id; | |
| } | |
| /** | |
| * Set username. | |
| * | |
| * @param string $username | |
| * | |
| * @return User | |
| */ | |
| public function setUsername($username) | |
| { | |
| $this->isChanged('username', $username); | |
| $this->username = $username; | |
| return $this; | |
| } | |
| /** | |
| * Set password. | |
| * | |
| * @param string $password | |
| * | |
| * @return User | |
| */ | |
| public function setPassword($password) | |
| { | |
| $this->password = $password; | |
| return $this; | |
| } | |
| /** | |
| * Set plain password. | |
| * | |
| * @return User | |
| */ | |
| public function setPlainPassword($plainPassword) | |
| { | |
| $this->plainPassword = $plainPassword; | |
| return $this; | |
| } | |
| /** | |
| * Set current password. | |
| * | |
| * @return User | |
| */ | |
| public function setCurrentPassword($currentPassword) | |
| { | |
| $this->currentPassword = $currentPassword; | |
| return $this; | |
| } | |
| /** | |
| * Set firstName. | |
| * | |
| * @param string $firstName | |
| * | |
| * @return User | |
| */ | |
| public function setFirstName($firstName) | |
| { | |
| $this->isChanged('firstName', $firstName); | |
| $this->firstName = $firstName; | |
| return $this; | |
| } | |
| /** | |
| * Get firstName. | |
| * | |
| * @return string | |
| */ | |
| public function getFirstName() | |
| { | |
| return $this->firstName; | |
| } | |
| /** | |
| * Set lastName. | |
| * | |
| * @param string $lastName | |
| * | |
| * @return User | |
| */ | |
| public function setLastName($lastName) | |
| { | |
| $this->isChanged('lastName', $lastName); | |
| $this->lastName = $lastName; | |
| return $this; | |
| } | |
| /** | |
| * Get lastName. | |
| * | |
| * @return string | |
| */ | |
| public function getLastName() | |
| { | |
| return $this->lastName; | |
| } | |
| /** | |
| * Get full name. | |
| * | |
| * @param bool $lastFirst | |
| */ | |
| public function getName($lastFirst = false): string | |
| { | |
| return ($lastFirst) ? $this->lastName.', '.$this->firstName : $this->firstName.' '.$this->lastName; | |
| } | |
| /** | |
| * Set email. | |
| * | |
| * @param string $email | |
| * | |
| * @return User | |
| */ | |
| public function setEmail($email) | |
| { | |
| $this->isChanged('email', $email); | |
| $this->email = $email; | |
| return $this; | |
| } | |
| /** | |
| * Get email. | |
| * | |
| * @return string | |
| */ | |
| public function getEmail() | |
| { | |
| return $this->email; | |
| } | |
| /** | |
| * Set role. | |
| * | |
| * @return User | |
| */ | |
| public function setRole(Role $role = null) | |
| { | |
| $this->isChanged('role', $role); | |
| $this->role = $role; | |
| return $this; | |
| } | |
| /** | |
| * Get role. | |
| * | |
| * @return Role | |
| */ | |
| public function getRole() | |
| { | |
| return $this->role; | |
| } | |
| /** | |
| * Set active permissions. | |
| * | |
| * @return User | |
| */ | |
| public function setActivePermissions(array $permissions) | |
| { | |
| $this->activePermissions = $permissions; | |
| return $this; | |
| } | |
| /** | |
| * Get active permissions. | |
| * | |
| * @return mixed | |
| */ | |
| public function getActivePermissions() | |
| { | |
| return $this->activePermissions; | |
| } | |
| /** | |
| * Set position. | |
| * | |
| * @param string $position | |
| * | |
| * @return User | |
| */ | |
| public function setPosition($position) | |
| { | |
| $this->isChanged('position', $position); | |
| $this->position = $position; | |
| return $this; | |
| } | |
| /** | |
| * Get position. | |
| * | |
| * @return string | |
| */ | |
| public function getPosition() | |
| { | |
| return $this->position; | |
| } | |
| /** | |
| * Set timezone. | |
| * | |
| * @param string $timezone | |
| * | |
| * @return User | |
| */ | |
| public function setTimezone($timezone) | |
| { | |
| $this->isChanged('timezone', $timezone); | |
| $this->timezone = $timezone; | |
| return $this; | |
| } | |
| /** | |
| * Get timezone. | |
| * | |
| * @return string | |
| */ | |
| public function getTimezone() | |
| { | |
| return $this->timezone; | |
| } | |
| /** | |
| * @return User | |
| */ | |
| public function setLocale(?string $locale) | |
| { | |
| $this->isChanged('locale', $locale); | |
| $this->locale = $locale; | |
| return $this; | |
| } | |
| /** | |
| * Get locale. | |
| * | |
| * @return string | |
| */ | |
| public function getLocale() | |
| { | |
| return $this->locale; | |
| } | |
| /** | |
| * Determines if user is admin. | |
| * | |
| * @return bool | |
| */ | |
| public function isAdmin() | |
| { | |
| if (null !== $this->role) { | |
| return $this->role->isAdmin(); | |
| } else { | |
| return false; | |
| } | |
| } | |
| /** | |
| * @return mixed | |
| */ | |
| public function getLastLogin() | |
| { | |
| return $this->lastLogin; | |
| } | |
| /** | |
| * @param mixed $lastLogin | |
| */ | |
| public function setLastLogin($lastLogin = null): void | |
| { | |
| if (empty($lastLogin)) { | |
| $lastLogin = new \DateTime(); | |
| } | |
| $this->lastLogin = $lastLogin; | |
| } | |
| /** | |
| * @return mixed | |
| */ | |
| public function getLastActive() | |
| { | |
| return $this->lastActive; | |
| } | |
| /** | |
| * @param mixed $lastActive | |
| */ | |
| public function setLastActive($lastActive = null): void | |
| { | |
| if (empty($lastActive)) { | |
| $lastActive = new \DateTime(); | |
| } | |
| $this->lastActive = $lastActive; | |
| } | |
| /** | |
| * @return mixed | |
| */ | |
| public function getPreferences() | |
| { | |
| return $this->preferences; | |
| } | |
| /** | |
| * @param mixed $preferences | |
| */ | |
| public function setPreferences(array $preferences): void | |
| { | |
| $this->preferences = $preferences; | |
| } | |
| /** | |
| * Set signature. | |
| * | |
| * @param string $signature | |
| * | |
| * @return User | |
| */ | |
| public function setSignature($signature) | |
| { | |
| $this->isChanged('signature', $signature); | |
| $this->signature = $signature; | |
| return $this; | |
| } | |
| /** | |
| * Get signature. | |
| * | |
| * @return string | |
| */ | |
| public function getSignature() | |
| { | |
| return $this->signature; | |
| } | |
| /** | |
| * Needed for SAML to work correctly. | |
| */ | |
| public function isEqualTo(UserInterface $user): bool | |
| { | |
| $thisUser = $this->getId().$this->getUserIdentifier().$this->getPassword(); | |
| $thatUser = $user->getId().$user->getUserIdentifier().$user->getPassword(); | |
| return $thisUser === $thatUser; | |
| } | |
| /** | |
| * @return bool | |
| */ | |
| public function isGuest() | |
| { | |
| return $this->guest; | |
| } | |
| public function getCacheNamespacesToDelete(): array | |
| { | |
| return [self::CACHE_NAMESPACE]; | |
| } | |
| } | |