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:
|
||||
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