Add sign-up form
parent
988cbba2d2
commit
9aff89e29a
@ -0,0 +1,14 @@
|
|||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sign-up {
|
||||||
|
width: 50%;
|
||||||
|
border: 1px solid rgba(0, 0, 0, .25);
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 auto;
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
import bsCustomFileInput from 'bs-custom-file-input';
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
bsCustomFileInput.init();
|
||||||
|
});
|
@ -0,0 +1,2 @@
|
|||||||
|
require('../../css/pages/security/sign-up.scss');
|
||||||
|
require('../../js/forms-file.js');
|
@ -0,0 +1,14 @@
|
|||||||
|
liip_imagine:
|
||||||
|
driver: "gd"
|
||||||
|
|
||||||
|
resolvers:
|
||||||
|
default:
|
||||||
|
web_path: ~
|
||||||
|
|
||||||
|
filter_sets:
|
||||||
|
cache: ~
|
||||||
|
|
||||||
|
user_avater:
|
||||||
|
filters:
|
||||||
|
scale:
|
||||||
|
dim: [120, 120]
|
@ -1,3 +1,4 @@
|
|||||||
twig:
|
twig:
|
||||||
default_path: '%kernel.project_dir%/templates'
|
default_path: '%kernel.project_dir%/templates'
|
||||||
form_themes: ['bootstrap_4_horizontal_layout.html.twig']
|
form_themes:
|
||||||
|
- 'bootstrap_4_horizontal_layout.html.twig'
|
@ -0,0 +1,9 @@
|
|||||||
|
vich_uploader:
|
||||||
|
db_driver: orm
|
||||||
|
|
||||||
|
mappings:
|
||||||
|
user_avatar:
|
||||||
|
namer: Vich\UploaderBundle\Naming\UniqidNamer
|
||||||
|
upload_destination: "%kernel.project_dir%/public/files/user_avatar"
|
||||||
|
uri_prefix: /files/user_avatar
|
||||||
|
inject_on_load: true
|
@ -0,0 +1,2 @@
|
|||||||
|
_liip_imagine:
|
||||||
|
resource: "@LiipImagineBundle/Resources/config/routing.yaml"
|
@ -0,0 +1,105 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Doctrine;
|
||||||
|
|
||||||
|
use App\Entity\User;
|
||||||
|
use Doctrine\Common\EventSubscriber;
|
||||||
|
use Doctrine\ORM\Event\LifecycleEventArgs;
|
||||||
|
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically encrypt user password
|
||||||
|
*
|
||||||
|
* This is a Doctrine event listener, to ensure the password is *always* encrypted
|
||||||
|
*
|
||||||
|
* @package App\Doctrine
|
||||||
|
* @see User
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class CryptPasswordListener implements EventSubscriber {
|
||||||
|
/**
|
||||||
|
* @var UserPasswordEncoderInterface The user's password encoder service
|
||||||
|
*/
|
||||||
|
private UserPasswordEncoderInterface $passwordEncoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
*
|
||||||
|
* Called using auto-wiring
|
||||||
|
*
|
||||||
|
* @param UserPasswordEncoderInterface $passwordEncoder The user's password encoder service
|
||||||
|
*/
|
||||||
|
public function __construct (UserPasswordEncoderInterface $passwordEncoder) {
|
||||||
|
$this->passwordEncoder = $passwordEncoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function getSubscribedEvents (): array {
|
||||||
|
return [
|
||||||
|
'prePersist',
|
||||||
|
'preUpdate',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When entity is inserted in database
|
||||||
|
*
|
||||||
|
* Automatically called by Doctrine
|
||||||
|
*
|
||||||
|
* @param LifecycleEventArgs $eventArgs The event arguments
|
||||||
|
*/
|
||||||
|
public function prePersist (LifecycleEventArgs $eventArgs): void {
|
||||||
|
// Check if entity is a User, else do nothing
|
||||||
|
$entity = $eventArgs->getEntity();
|
||||||
|
if (!$entity instanceof User) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->encodePassword($entity);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* When entity is updated in database
|
||||||
|
*
|
||||||
|
* Automatically called by Doctrine
|
||||||
|
*
|
||||||
|
* @param LifecycleEventArgs $eventArgs The event arguments
|
||||||
|
*/
|
||||||
|
public function preUpdate (LifecycleEventArgs $eventArgs): void {
|
||||||
|
// Check if entity is a User, else do nothing
|
||||||
|
$entity = $eventArgs->getEntity();
|
||||||
|
if (!$entity instanceof User) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->encodePassword($entity);
|
||||||
|
|
||||||
|
// Force update of entity
|
||||||
|
$doctrine = $eventArgs->getEntityManager();
|
||||||
|
$doctrine->getUnitOfWork()->recomputeSingleEntityChangeSet(
|
||||||
|
$doctrine->getClassMetadata(get_class($entity)),
|
||||||
|
$entity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform teh password encryption (if necessary)
|
||||||
|
*
|
||||||
|
* @param User $user The user
|
||||||
|
*/
|
||||||
|
private function encodePassword (User $user): void {
|
||||||
|
// Mot de passe modifié ?
|
||||||
|
if (empty($user->getPlainPassword())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crypt the password
|
||||||
|
$user->setPassword(
|
||||||
|
$this->passwordEncoder->encodePassword(
|
||||||
|
$user,
|
||||||
|
$user->getPlainPassword()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Entity;
|
|
||||||
|
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Entity(repositoryClass="App\Repository\LanguageRepository")
|
|
||||||
*/
|
|
||||||
class Language {
|
|
||||||
/**
|
|
||||||
* @ORM\Id()
|
|
||||||
* @ORM\GeneratedValue()
|
|
||||||
* @ORM\Column(type="integer")
|
|
||||||
*/
|
|
||||||
private $id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Column(type="string", length=50)
|
|
||||||
*/
|
|
||||||
private $name;
|
|
||||||
|
|
||||||
public function getId (): ?int {
|
|
||||||
return $this->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName (): ?string {
|
|
||||||
return $this->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setName (string $name): self {
|
|
||||||
$this->name = $name;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form;
|
||||||
|
|
||||||
|
use App\Entity\User;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\EmailType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\LanguageType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
use Vich\UploaderBundle\Form\Type\VichImageType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Security : sign-up form
|
||||||
|
*
|
||||||
|
* @package App\Form
|
||||||
|
*/
|
||||||
|
class SecuritySignUpForm extends AbstractBootstrapForm {
|
||||||
|
/**
|
||||||
|
* @var TranslatorInterface The translation service
|
||||||
|
*/
|
||||||
|
private TranslatorInterface $translatorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor
|
||||||
|
*
|
||||||
|
* Called using auto-wiring
|
||||||
|
*
|
||||||
|
* @param TranslatorInterface $translatorInterface The translation service
|
||||||
|
*/
|
||||||
|
public function __construct (TranslatorInterface $translatorInterface) {
|
||||||
|
$this->translatorInterface = $translatorInterface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function buildForm (FormBuilderInterface $builder, array $options) {
|
||||||
|
parent::buildForm($builder, $options);
|
||||||
|
|
||||||
|
$builder
|
||||||
|
->add(
|
||||||
|
'email',
|
||||||
|
EmailType::class,
|
||||||
|
[
|
||||||
|
'label_format' => 'user.email',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'plainPassword',
|
||||||
|
RepeatedType::class,
|
||||||
|
[
|
||||||
|
'type' => PasswordType::class,
|
||||||
|
'first_options' => [
|
||||||
|
'label_format' => 'user.password',
|
||||||
|
],
|
||||||
|
'second_options' => [
|
||||||
|
'label_format' => 'user.password_confirm',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'gender',
|
||||||
|
ChoiceType::class,
|
||||||
|
[
|
||||||
|
'choices' => User::getGenders(),
|
||||||
|
'choice_label' => function (string $gender) {
|
||||||
|
return $gender ? $this->translatorInterface->trans('user.genders.' . $gender, [], 'security') : '';
|
||||||
|
},
|
||||||
|
'choice_translation_domain' => false,
|
||||||
|
'label_format' => 'user.gender',
|
||||||
|
'required' => false,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'firstname',
|
||||||
|
TextType::class,
|
||||||
|
[
|
||||||
|
'label_format' => 'user.firstname',
|
||||||
|
'required' => false,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'name',
|
||||||
|
TextType::class,
|
||||||
|
[
|
||||||
|
'label_format' => 'user.name',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'language',
|
||||||
|
LanguageType::class,
|
||||||
|
[
|
||||||
|
'choice_self_translation' => true,
|
||||||
|
'label_format' => 'user.language',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'avatarFile',
|
||||||
|
VichImageType::class,
|
||||||
|
[
|
||||||
|
'label_format' => 'user.avatar',
|
||||||
|
'translation_domain' => 'security',
|
||||||
|
'required' => false,
|
||||||
|
'imagine_pattern' => 'url_avatar',
|
||||||
|
'storage_resolve_method' => VichImageType::STORAGE_RESOLVE_PATH_RELATIVE,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function configureOptions (OptionsResolver $resolver) {
|
||||||
|
parent::configureOptions($resolver);
|
||||||
|
|
||||||
|
$resolver->setDefaults(
|
||||||
|
[
|
||||||
|
'translation_domain' => 'security',
|
||||||
|
'data_class' => User::class,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20200707131948 extends AbstractMigration {
|
||||||
|
public function getDescription (): string {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up (Schema $schema): void {
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user ADD updated_at DATETIME NOT NULL, ADD avatar_original_name VARCHAR(255) DEFAULT NULL, ADD avatar_mime_type VARCHAR(255) DEFAULT NULL, ADD avatar_size INT DEFAULT NULL, ADD avatar_dimensions LONGTEXT DEFAULT NULL COMMENT \'(DC2Type:simple_array)\', DROP inactive, CHANGE gender gender VARCHAR(25) DEFAULT NULL, CHANGE avatar avatar_name VARCHAR(255) DEFAULT NULL'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down (Schema $schema): void {
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user ADD avatar varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`, ADD inactive tinyint(1) NOT NULL, DROP updated_at, DROP avatar_name, DROP avatar_original_name, DROP avatar_mime_type, DROP avatar_size, DROP avatar_dimensions, CHANGE gender gender smallint NOT NULL'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20200707135616 extends AbstractMigration {
|
||||||
|
public function getDescription (): string {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up (Schema $schema): void {
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user DROP FOREIGN KEY FK_8D93D64982F1BAF4');
|
||||||
|
$this->addSql('DROP TABLE language');
|
||||||
|
$this->addSql('DROP INDEX IDX_8D93D64982F1BAF4 ON user');
|
||||||
|
$this->addSql('ALTER TABLE user ADD language varchar(2) NOT NULL, DROP language_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down (Schema $schema): void {
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('CREATE TABLE language (id int AUTO_INCREMENT NOT NULL, name varchar(50) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, code varchar(2) CHARACTER SET utf8mb4 NOT NULL COLLATE `utf8mb4_unicode_ci`, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB COMMENT = \'\' '
|
||||||
|
);
|
||||||
|
$this->addSql('ALTER TABLE user ADD language_id int DEFAULT NULL, DROP language');
|
||||||
|
$this->addSql('ALTER TABLE user ADD CONSTRAINT FK_8D93D64982F1BAF4 FOREIGN KEY (language_id) REFERENCES language (id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_8D93D64982F1BAF4 ON user (language_id)');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20200709102824 extends AbstractMigration {
|
||||||
|
public function getDescription (): string {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up (Schema $schema): void {
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user CHANGE fist_name fistname varchar(255) DEFAULT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down (Schema $schema): void {
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user CHANGE fistname fist_name varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types = 1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20200709103321 extends AbstractMigration {
|
||||||
|
public function getDescription (): string {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up (Schema $schema): void {
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user CHANGE fistname firstname varchar(255) DEFAULT NULL');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down (Schema $schema): void {
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||||
|
|
||||||
|
$this->addSql('ALTER TABLE user CHANGE firstname fistname varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL COLLATE `utf8mb4_unicode_ci`');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<style>
|
||||||
|
.custom-file-label::after {
|
||||||
|
content : '{{ 'form.browse'|trans({}, 'messages') }}';
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,46 @@
|
|||||||
|
{% trans_default_domain 'security' %}
|
||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}{{ 'sign.up'|trans }}{% endblock %}
|
||||||
|
|
||||||
|
{% block stylesheets %}
|
||||||
|
{{ parent() }}
|
||||||
|
{{ encore_entry_link_tags('security/sign-up') }}
|
||||||
|
{% include '_form_browse.html.twig' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
<section id="sign-up">
|
||||||
|
<h1>{{ 'sign.up'|trans }}</h1>
|
||||||
|
|
||||||
|
{{ form_start(form) }}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
{{ form_row(form.email) }}
|
||||||
|
{{ form_row(form.plainPassword.first) }}
|
||||||
|
{{ form_row(form.plainPassword.second) }}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
{{ form_row(form.gender) }}
|
||||||
|
{{ form_row(form.firstname) }}
|
||||||
|
{{ form_row(form.name) }}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
{{ form_row(form.language) }}
|
||||||
|
{{ form_row(form.avatarFile) }}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div class="form-group form-buttons">
|
||||||
|
<button class="btn btn-lg btn-primary" type="submit">{{ 'sign.up'|trans }}</button>
|
||||||
|
</div>
|
||||||
|
{{ form_end(form) }}
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascripts %}
|
||||||
|
{{ parent() }}
|
||||||
|
{{ encore_entry_script_tags('security/sign-up') }}
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue