Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\ConfigBundle\Form\Type\ConfigFileType;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\Validator\Constraints\File;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class ConfigType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
protected CoreParametersHelper $parameters,
|
||||
protected TranslatorInterface $translator,
|
||||
) {
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$samlEntityIdChoices = ['', rtrim($this->parameters->get('mautic.site_url'), '/')];
|
||||
if (!empty($this->parameters->get('mautic.subdomain_url'))) {
|
||||
$samlEntityIdChoices[] = rtrim($this->parameters->get('mautic.subdomain_url'), '/');
|
||||
}
|
||||
$builder->add('saml_idp_entity_id', ChoiceType::class,
|
||||
[
|
||||
'choices' => array_combine($samlEntityIdChoices, $samlEntityIdChoices),
|
||||
'label' => 'mautic.user.config.form.saml.idp_entity_id_label',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'required' => true,
|
||||
'multiple' => false,
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
]);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_metadata',
|
||||
ConfigFileType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.metadata',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'tooltip' => 'mautic.user.config.form.saml.idp.metadata.tooltip',
|
||||
'rows' => 10,
|
||||
],
|
||||
'required' => false,
|
||||
'constraints' => [
|
||||
new File(
|
||||
[
|
||||
'mimeTypes' => ['text/plain', 'text/xml', 'application/xml'],
|
||||
'mimeTypesMessage' => 'mautic.core.invalid_file_type',
|
||||
]
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_own_certificate',
|
||||
ConfigFileType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.own_certificate',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'tooltip' => 'mautic.user.config.form.saml.idp.own_certificate.tooltip',
|
||||
],
|
||||
'required' => false,
|
||||
'constraints' => [
|
||||
new File(
|
||||
[
|
||||
'mimeTypes' => ['text/plain'],
|
||||
'mimeTypesMessage' => 'mautic.core.invalid_file_type',
|
||||
]
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_own_private_key',
|
||||
ConfigFileType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.own_private_key',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'tooltip' => 'mautic.user.config.form.saml.idp.own_private_key.tooltip',
|
||||
],
|
||||
'required' => false,
|
||||
'constraints' => [
|
||||
new File(
|
||||
[
|
||||
'mimeTypes' => ['text/plain'],
|
||||
'mimeTypesMessage' => 'mautic.core.invalid_file_type',
|
||||
]
|
||||
),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_own_password',
|
||||
PasswordType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.own_password',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'tooltip' => 'mautic.user.config.form.saml.idp.own_password.tooltip',
|
||||
],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_email_attribute',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.attribute_email',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'empty_data' => 'EmailAddress',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_username_attribute',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.attribute_username',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_firstname_attribute',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.attribute_firstname',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'empty_data' => 'FirstName',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_lastname_attribute',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.attribute_lastname',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'empty_data' => 'LastName',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'saml_idp_default_role',
|
||||
RoleListType::class,
|
||||
[
|
||||
'label' => 'mautic.user.config.form.saml.idp.default_role',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'data-placeholder' => $this->translator->trans('mautic.user.config.form.saml.idp.disable_creation'),
|
||||
'tooltip' => 'mautic.user.config.form.saml.idp.default_role.tooltip',
|
||||
],
|
||||
'required' => false,
|
||||
'placeholder' => '',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function buildView(FormView $view, FormInterface $form, array $options): void
|
||||
{
|
||||
$view->vars['entityId'] = $this->parameters->get('mautic.saml_idp_entity_id');
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'userconfig';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Form\Type\FormButtonsType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints\Length;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class ContactType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @param FormBuilderInterface<array<mixed>|null> $builder
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add(
|
||||
'msg_subject',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.email.subject',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => ['class' => 'form-control'],
|
||||
'constraints' => [
|
||||
new NotBlank(['message' => 'Subject should not be blank.']),
|
||||
new Length(['min' => 3]),
|
||||
],
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'msg_body',
|
||||
TextareaType::class,
|
||||
[
|
||||
'label' => 'mautic.user.user.contact.message',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'rows' => 10,
|
||||
],
|
||||
'constraints' => [
|
||||
new NotBlank(['message' => 'Message should not be blank.']),
|
||||
new Length(['min' => 5]),
|
||||
],
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'entity',
|
||||
HiddenType::class,
|
||||
[
|
||||
'attr' => [
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'id',
|
||||
HiddenType::class,
|
||||
[
|
||||
'attr' => [
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
]
|
||||
)
|
||||
->add(
|
||||
'returnUrl',
|
||||
HiddenType::class,
|
||||
[
|
||||
'attr' => [
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
]
|
||||
)
|
||||
->add('buttons', FormButtonsType::class, [
|
||||
'save_text' => 'mautic.user.user.contact.send',
|
||||
'save_icon' => 'ri-send-plane-line',
|
||||
'apply_text' => false,
|
||||
]);
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Form\EventListener\CleanFormSubscriber;
|
||||
use Mautic\UserBundle\Form\Validator\Constraints\NotWeak;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class PasswordResetConfirmType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->addEventSubscriber(new CleanFormSubscriber([]));
|
||||
|
||||
$builder->add(
|
||||
'identifier',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.user.auth.form.loginusername',
|
||||
'label_attr' => ['class' => 'sr-only'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'preaddon' => 'ri-user-6-fill',
|
||||
'placeholder' => 'mautic.user.auth.form.loginusername',
|
||||
],
|
||||
'required' => true,
|
||||
'constraints' => [
|
||||
new Assert\NotBlank(['message' => 'mautic.user.user.passwordreset.notblank']),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'plainPassword',
|
||||
RepeatedType::class,
|
||||
[
|
||||
'first_name' => 'password',
|
||||
'first_options' => [
|
||||
'label' => 'mautic.core.password',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => 'mautic.user.user.passwordreset.password.placeholder',
|
||||
'tooltip' => 'mautic.user.user.form.help.passwordrequirements',
|
||||
'preaddon' => 'ri-lock-fill',
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
'required' => true,
|
||||
'error_bubbling' => false,
|
||||
'constraints' => [
|
||||
new Assert\NotBlank(['message' => 'mautic.user.user.passwordreset.notblank']),
|
||||
new Assert\Length([
|
||||
'min' => 6,
|
||||
'minMessage' => 'mautic.user.user.password.minlength',
|
||||
]),
|
||||
new NotWeak([
|
||||
'message' => 'mautic.user.user.password.weak',
|
||||
]),
|
||||
],
|
||||
],
|
||||
'second_name' => 'confirm',
|
||||
'second_options' => [
|
||||
'label' => 'mautic.user.user.form.passwordconfirm',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => 'mautic.user.user.passwordreset.confirm.placeholder',
|
||||
'tooltip' => 'mautic.user.user.form.help.passwordrequirements',
|
||||
'preaddon' => 'ri-lock-fill',
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
'required' => true,
|
||||
'error_bubbling' => false,
|
||||
'constraints' => [
|
||||
new Assert\NotBlank(['message' => 'mautic.user.user.passwordreset.notblank']),
|
||||
],
|
||||
],
|
||||
'type' => PasswordType::class,
|
||||
'invalid_message' => 'mautic.user.user.password.mismatch',
|
||||
'required' => true,
|
||||
'error_bubbling' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'submit',
|
||||
SubmitType::class,
|
||||
[
|
||||
'attr' => [
|
||||
'class' => 'btn btn-lg btn-primary btn-block',
|
||||
],
|
||||
'label' => 'mautic.user.user.passwordreset.reset',
|
||||
]
|
||||
);
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'passwordresetconfirm';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Form\EventListener\CleanFormSubscriber;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class PasswordResetType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->addEventSubscriber(new CleanFormSubscriber([]));
|
||||
|
||||
$builder->add(
|
||||
'identifier',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.user.auth.form.loginusername',
|
||||
'label_attr' => ['class' => 'sr-only'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'preaddon' => 'ri-user-6-fill',
|
||||
'placeholder' => 'mautic.user.auth.form.loginusername',
|
||||
],
|
||||
'constraints' => [
|
||||
new Assert\NotBlank(['message' => 'mautic.user.user.passwordreset.notblank']),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'submit',
|
||||
SubmitType::class,
|
||||
[
|
||||
'attr' => [
|
||||
'class' => 'btn btn-lg btn-primary btn-block',
|
||||
],
|
||||
'label' => 'mautic.user.user.passwordreset.reset',
|
||||
]
|
||||
);
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'passwordreset';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\Options;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class PermissionListType extends AbstractType
|
||||
{
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setRequired(['bundle', 'level']);
|
||||
|
||||
$resolver->setDefaults([
|
||||
'multiple' => true,
|
||||
'expanded' => true,
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => fn (Options $options): array => [
|
||||
'data-permission' => $options['bundle'].':'.$options['level'],
|
||||
'onchange' => 'Mautic.onPermissionChange(this, \''.$options['bundle'].'\')',
|
||||
],
|
||||
'choices_as_values' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
public function getBlockPrefix(): string
|
||||
{
|
||||
return 'permissionlist';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Valid;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class PermissionsType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
foreach ($options['permissionsConfig'] as $bundle => $config) {
|
||||
$builder->add(
|
||||
$bundle,
|
||||
HiddenType::class,
|
||||
[
|
||||
'data' => 'newbundle',
|
||||
'label' => false,
|
||||
'mapped' => false,
|
||||
]
|
||||
);
|
||||
$config['permissionObject']->buildForm($builder, $options, $config['data']);
|
||||
}
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'permissionsConfig' => [],
|
||||
'constraints' => [new Valid()],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\UserBundle\Model\RoleModel;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class RoleListType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private RoleModel $roleModel,
|
||||
) {
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'choices' => $this->getRoleChoices(),
|
||||
'expanded' => false,
|
||||
'multiple' => false,
|
||||
'required' => false,
|
||||
'placeholder' => 'mautic.core.form.chooseone',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
private function getRoleChoices(): array
|
||||
{
|
||||
$choices = [];
|
||||
$roles = $this->roleModel->getRepository()->getEntities(
|
||||
[
|
||||
'filter' => [
|
||||
'force' => [
|
||||
[
|
||||
'column' => 'r.isPublished',
|
||||
'expr' => 'eq',
|
||||
'value' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
foreach ($roles as $role) {
|
||||
$choices[$role->getName(true)] = $role->getId();
|
||||
}
|
||||
|
||||
// sort by name
|
||||
ksort($choices);
|
||||
|
||||
return $choices;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\CoreBundle\Form\EventListener\CleanFormSubscriber;
|
||||
use Mautic\CoreBundle\Form\EventListener\FormExitSubscriber;
|
||||
use Mautic\CoreBundle\Form\Type\FormButtonsType;
|
||||
use Mautic\CoreBundle\Form\Type\YesNoButtonGroupType;
|
||||
use Mautic\UserBundle\Entity\Role;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Component\Validator\Constraints\Valid;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<RoleType>
|
||||
*/
|
||||
class RoleType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->addEventSubscriber(new CleanFormSubscriber(['description' => 'html']));
|
||||
$builder->addEventSubscriber(new FormExitSubscriber('user.role', $options));
|
||||
|
||||
$builder->add(
|
||||
'name',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.core.name',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => ['class' => 'form-control'],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'description',
|
||||
TextareaType::class,
|
||||
[
|
||||
'label' => 'mautic.core.description',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => ['class' => 'form-control editor'],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add('isAdmin', YesNoButtonGroupType::class, [
|
||||
'label' => 'mautic.user.role.form.isadmin',
|
||||
'attr' => [
|
||||
'onchange' => 'Mautic.togglePermissionVisibility();',
|
||||
'tooltip' => 'mautic.user.role.form.isadmin.tooltip',
|
||||
],
|
||||
]);
|
||||
|
||||
// add a normal text field, but add your transformer to it
|
||||
$hidden = ($options['data']->isAdmin()) ? ' hide' : '';
|
||||
|
||||
$builder->add(
|
||||
'permissions',
|
||||
PermissionsType::class,
|
||||
[
|
||||
'label' => 'mautic.user.role.permissions',
|
||||
'mapped' => false, // we'll have to manually build the permissions for persisting
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'class' => $hidden,
|
||||
],
|
||||
'permissionsConfig' => $options['permissionsConfig'],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add('buttons', FormButtonsType::class);
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Role::class,
|
||||
'constraints' => [new Valid()],
|
||||
'permissionsConfig' => [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Mautic\UserBundle\Model\UserModel;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<array<mixed>>
|
||||
*/
|
||||
class UserListType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var array<string,int>
|
||||
*/
|
||||
private array $choices = [];
|
||||
|
||||
public function __construct(
|
||||
private UserModel $userModel,
|
||||
) {
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'choices' => $this->getUserChoices(),
|
||||
'expanded' => false,
|
||||
'multiple' => true,
|
||||
'required' => false,
|
||||
'placeholder' => 'mautic.core.form.chooseone',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function getParent(): ?string
|
||||
{
|
||||
return ChoiceType::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,int>
|
||||
*/
|
||||
private function getUserChoices(): array
|
||||
{
|
||||
if ($this->choices) {
|
||||
return $this->choices;
|
||||
}
|
||||
|
||||
$users = $this->userModel->getRepository()->getEntities(
|
||||
[
|
||||
'filter' => [
|
||||
'force' => [
|
||||
[
|
||||
'column' => 'u.isPublished',
|
||||
'expr' => 'eq',
|
||||
'value' => true,
|
||||
],
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$this->choices[$user->getName(true).' ('.$user->getId().')'] = $user->getId();
|
||||
}
|
||||
|
||||
// sort by user name
|
||||
ksort($this->choices);
|
||||
|
||||
return $this->choices;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<mixed>
|
||||
*/
|
||||
class UserPreferencesType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
// Theme
|
||||
$builder->add(
|
||||
'theme',
|
||||
HiddenType::class,
|
||||
[
|
||||
'label' => 'mautic.user.preferences.theme',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
// Reduce Transparency
|
||||
$builder->add(
|
||||
'reduce_transparency',
|
||||
HiddenType::class,
|
||||
[
|
||||
'label' => 'mautic.user.preferences.reduce_transparency',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
// Reduce Motion
|
||||
$builder->add(
|
||||
'reduce_motion',
|
||||
HiddenType::class,
|
||||
[
|
||||
'label' => 'mautic.user.preferences.reduce_motion',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
// Contrast Borders
|
||||
$builder->add(
|
||||
'contrast_borders',
|
||||
HiddenType::class,
|
||||
[
|
||||
'label' => 'mautic.user.preferences.contrast_borders',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
// Enable Underlines
|
||||
$builder->add(
|
||||
'enable_underlines',
|
||||
HiddenType::class,
|
||||
[
|
||||
'label' => 'mautic.user.preferences.enable_underlines',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\UserBundle\Form\Type;
|
||||
|
||||
use Doctrine\Common\Collections\Order;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
use Mautic\CoreBundle\Form\EventListener\CleanFormSubscriber;
|
||||
use Mautic\CoreBundle\Form\EventListener\FormExitSubscriber;
|
||||
use Mautic\CoreBundle\Form\Type\FormButtonsType;
|
||||
use Mautic\CoreBundle\Form\Type\YesNoButtonGroupType;
|
||||
use Mautic\CoreBundle\Helper\LanguageHelper;
|
||||
use Mautic\UserBundle\Entity\Role;
|
||||
use Mautic\UserBundle\Entity\User;
|
||||
use Mautic\UserBundle\Model\UserModel;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TimezoneType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @extends AbstractType<User>
|
||||
*/
|
||||
class UserType extends AbstractType
|
||||
{
|
||||
public function __construct(
|
||||
private TranslatorInterface $translator,
|
||||
private UserModel $model,
|
||||
private LanguageHelper $languageHelper,
|
||||
) {
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder->addEventSubscriber(new CleanFormSubscriber(['signature' => 'html', 'email' => 'email']));
|
||||
$builder->addEventSubscriber(new FormExitSubscriber('user.user', $options));
|
||||
|
||||
$builder->add(
|
||||
'username',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.core.username',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'preaddon' => 'ri-user-6-fill',
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'firstName',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.core.firstname',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => ['class' => 'form-control'],
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'lastName',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.core.lastname',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => ['class' => 'form-control'],
|
||||
]
|
||||
);
|
||||
|
||||
$positions = $this->model->getLookupResults('position', null, 0);
|
||||
$builder->add(
|
||||
'position',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'mautic.core.position',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'data-options' => json_encode($positions),
|
||||
],
|
||||
'required' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'email',
|
||||
EmailType::class,
|
||||
[
|
||||
'label' => 'mautic.core.type.email',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'preaddon' => 'ri-mail-line',
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$existing = (!empty($options['data']) && $options['data']->getId());
|
||||
$placeholder = ($existing) ?
|
||||
$this->translator->trans('mautic.user.user.form.passwordplaceholder') : '';
|
||||
$required = ($existing) ? false : true;
|
||||
$builder->add(
|
||||
'plainPassword',
|
||||
RepeatedType::class,
|
||||
[
|
||||
'first_name' => 'password',
|
||||
'first_options' => [
|
||||
'label' => 'mautic.core.password',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => $placeholder,
|
||||
'tooltip' => 'mautic.user.user.form.help.passwordrequirements',
|
||||
'preaddon' => 'ri-lock-fill',
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
'required' => $required,
|
||||
'error_bubbling' => false,
|
||||
],
|
||||
'second_name' => 'confirm',
|
||||
'second_options' => [
|
||||
'label' => 'mautic.user.user.form.passwordconfirm',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
'placeholder' => $placeholder,
|
||||
'tooltip' => 'mautic.user.user.form.help.passwordrequirements',
|
||||
'preaddon' => 'ri-lock-fill',
|
||||
'autocomplete' => 'off',
|
||||
],
|
||||
'required' => $required,
|
||||
'error_bubbling' => false,
|
||||
],
|
||||
'type' => PasswordType::class,
|
||||
'invalid_message' => 'mautic.user.user.password.mismatch',
|
||||
'required' => $required,
|
||||
'error_bubbling' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'timezone',
|
||||
TimezoneType::class,
|
||||
[
|
||||
'label' => 'mautic.core.timezone',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'multiple' => false,
|
||||
'placeholder' => 'mautic.user.user.form.defaulttimezone',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'locale',
|
||||
ChoiceType::class,
|
||||
[
|
||||
'choices' => $this->getSupportedLanguageChoices(),
|
||||
'label' => 'mautic.core.language',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'multiple' => false,
|
||||
'placeholder' => 'mautic.user.user.form.defaultlocale',
|
||||
]
|
||||
);
|
||||
|
||||
$builder->add(
|
||||
'preferences',
|
||||
UserPreferencesType::class,
|
||||
[
|
||||
'label' => false,
|
||||
]
|
||||
);
|
||||
|
||||
$defaultSignature = '';
|
||||
if (isset($options['data']) && null === $options['data']->getSignature()) {
|
||||
$defaultSignature = $this->translator->trans('mautic.email.default.signature', ['%from_name%' => '|FROM_NAME|']);
|
||||
} elseif (isset($options['data'])) {
|
||||
$defaultSignature = $options['data']->getSignature();
|
||||
}
|
||||
|
||||
$builder->add(
|
||||
'signature',
|
||||
TextareaType::class,
|
||||
[
|
||||
'label' => 'mautic.email.token.signature',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'required' => false,
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'data' => $defaultSignature,
|
||||
'help' => 'mautic.user.config.signature.helper',
|
||||
]
|
||||
);
|
||||
|
||||
if (empty($options['in_profile'])) {
|
||||
$builder->add(
|
||||
$builder->create(
|
||||
'role',
|
||||
EntityType::class,
|
||||
[
|
||||
'label' => 'mautic.user.role',
|
||||
'label_attr' => ['class' => 'control-label'],
|
||||
'attr' => [
|
||||
'class' => 'form-control',
|
||||
],
|
||||
'class' => Role::class,
|
||||
'choice_label' => 'name',
|
||||
'query_builder' => fn (EntityRepository $er) => $er->createQueryBuilder('r')
|
||||
->where('r.isPublished = true')
|
||||
->orderBy('r.name', Order::Ascending->value),
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$builder->add('isPublished', YesNoButtonGroupType::class);
|
||||
|
||||
$builder->add('buttons', FormButtonsType::class);
|
||||
} else {
|
||||
$builder->add(
|
||||
'buttons',
|
||||
FormButtonsType::class,
|
||||
[
|
||||
'save_text' => 'mautic.core.form.apply',
|
||||
'apply_text' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (!empty($options['action'])) {
|
||||
$builder->setAction($options['action']);
|
||||
}
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults(
|
||||
[
|
||||
'data_class' => User::class,
|
||||
'validation_groups' => [
|
||||
User::class,
|
||||
'determineValidationGroups',
|
||||
],
|
||||
'ignore_formexit' => false,
|
||||
'in_profile' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function getSupportedLanguageChoices(): array
|
||||
{
|
||||
// Get the list of available languages
|
||||
$languages = $this->languageHelper->fetchLanguages(false, false);
|
||||
$choices = [];
|
||||
|
||||
foreach ($languages as $code => $langData) {
|
||||
$choices[$langData['name']] = $code;
|
||||
}
|
||||
$choices = array_merge($choices, array_flip($this->languageHelper->getSupportedLanguages()));
|
||||
|
||||
// Alpha sort the languages by name
|
||||
ksort($choices);
|
||||
|
||||
return $choices;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\UserBundle\Form\Validator\Constraints;
|
||||
|
||||
use Mautic\UserBundle\Model\PasswordStrengthEstimatorModel;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
||||
final class NotWeak extends Constraint
|
||||
{
|
||||
public const TOO_WEAK = 'f61e730a-284e-11eb-adc1-0242ac120002';
|
||||
|
||||
protected const ERROR_NAMES = [
|
||||
self::TOO_WEAK => 'PASSWORD_TOO_WEAK_ERROR',
|
||||
];
|
||||
|
||||
public string $message = 'This password is too weak. Consider using a stronger password.';
|
||||
|
||||
public int $score = PasswordStrengthEstimatorModel::MINIMUM_PASSWORD_STRENGTH_ALLOWED;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\UserBundle\Form\Validator\Constraints;
|
||||
|
||||
use Mautic\UserBundle\Model\PasswordStrengthEstimatorModel;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
use Symfony\Component\Validator\ConstraintValidator;
|
||||
use Symfony\Component\Validator\Exception\UnexpectedTypeException;
|
||||
|
||||
final class NotWeakValidator extends ConstraintValidator
|
||||
{
|
||||
public function __construct(private PasswordStrengthEstimatorModel $passwordStrengthEstimatorModel)
|
||||
{
|
||||
}
|
||||
|
||||
public function validate(mixed $value, Constraint $constraint): void
|
||||
{
|
||||
if (!$constraint instanceof NotWeak) {
|
||||
throw new UnexpectedTypeException($constraint, NotWeak::class);
|
||||
}
|
||||
|
||||
if ($this->passwordStrengthEstimatorModel->validate($value, $constraint->score)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context->buildViolation($constraint->message)
|
||||
->setCode(NotWeak::TOO_WEAK)
|
||||
->addViolation();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user