diff --git a/app/Resources/views/admin/association/membership/register.html.twig b/app/Resources/views/admin/association/membership/register.html.twig new file mode 100644 index 000000000..47a384b81 --- /dev/null +++ b/app/Resources/views/admin/association/membership/register.html.twig @@ -0,0 +1,41 @@ +{% extends ':admin/association/membership:_base.html.twig' %} + +{% block page_title %}Formulaire d'inscription à l'AFUP{% endblock %} + +{% block submenu %} + {{ render(controller( + 'AppBundle\\Controller\\SecondaryMenuController::displayAction', + { 'feuille_id': constant('Afup\\Site\\Corporate\\Feuille::ID_FEUILLE_ASSOCIATION') } + )) }} +{% endblock %} + +{% block page_content %} +
+ {{ form_start(form) }} +
+ Information +
+ {{ form_errors(form) }} + {{ form_row(form.civility) }} + {{ form_row(form.userCommonInfo.lastName) }} + {{ form_row(form.userCommonInfo.firstName) }} + {{ form_row(form.userCommonInfo.username) }} + {{ form_row(form.userCommonInfo.email) }} + {{ form_row(form.userCommonInfo.address) }} + {{ form_row(form.userCommonInfo.zipcode) }} + {{ form_row(form.userCommonInfo.city) }} + {{ form_row(form.country) }} + {{ form_row(form.userCommonInfo.phone) }} + {{ form_row(form.mobilephone) }} + {{ form_row(form.nearestOffice) }} +
+ {{ form_widget(form.userCommonInfo.password) }} +
+
+
+
+ {{ form_widget(form.userCommonInfo.save, {attr: { "class": "button button--call-to-action"}}) }} +
+ {{ form_end(form) }} +
+{% endblock %} diff --git a/app/Resources/views/form_theme.html.twig b/app/Resources/views/form_theme.html.twig new file mode 100644 index 000000000..352a281b2 --- /dev/null +++ b/app/Resources/views/form_theme.html.twig @@ -0,0 +1,57 @@ +{% use 'form_div_layout.html.twig' %} + +{% block form_row %} + {{ parent() }} + {% if form.vars.help ?? false %} +
+ + {{ form.vars.help }} +
+ {% endif %} +{% endblock form_row %} + +{# TODO : A supprimer une fois monté de version suffisante pour que ce soit SF qu'ils fassent la gestion de "*" dans le cas où le champs est required #} +{% block form_label %} + {% if label is not same as(false) -%} + {% if not compound -%} + {% set label_attr = label_attr|merge({'for': id}) %} + {%- endif -%} + {% if required -%} + {% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %} + {%- endif -%} + {% if label is empty -%} + {%- if label_format is not empty -%} + {% set label = label_format|replace({ + '%name%': name, + '%id%': id, + }) %} + {%- else -%} + {% set label = name|humanize %} + {%- endif -%} + {%- endif -%} + <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}> + {%- if translation_domain is same as(false) -%} + {{- label -}} + {%- else -%} + {{- label|trans({}, translation_domain) -}} + {%- endif -%} + {# OVERRIDE #} + {% if required -%} + * + {%- endif -%} + {# END OVERRIDE #} + + {%- endif -%} +{% endblock form_label %} + +{%- block form_errors -%} + {%- if errors|length > 0 -%} + {%- for error in errors -%} +
+ + {{ error.message }} +
+ {%- endfor -%} + + {%- endif -%} +{%- endblock form_errors -%} diff --git a/app/Resources/views/form_theme_errors.html.twig b/app/Resources/views/form_theme_errors.html.twig deleted file mode 100644 index 5ba313f89..000000000 --- a/app/Resources/views/form_theme_errors.html.twig +++ /dev/null @@ -1,13 +0,0 @@ -{% use 'form_theme_help.html.twig' %} - -{%- block form_errors -%} - {%- if errors|length > 0 -%} - {%- for error in errors -%} -
- - {{ error.message }} -
- {%- endfor -%} - - {%- endif -%} -{%- endblock form_errors -%} diff --git a/app/Resources/views/form_theme_help.html.twig b/app/Resources/views/form_theme_help.html.twig deleted file mode 100644 index 033731e58..000000000 --- a/app/Resources/views/form_theme_help.html.twig +++ /dev/null @@ -1,11 +0,0 @@ -{% use 'form_div_layout.html.twig' %} - -{% block form_row %} - {{ parent() }} - {% if form.vars.help ?? false %} -
- - {{ form.vars.help }} -
- {% endif %} -{% endblock form_row %} diff --git a/app/Resources/views/site/become_member.html.twig b/app/Resources/views/site/become_member.html.twig index 410c61390..d15b197f0 100644 --- a/app/Resources/views/site/become_member.html.twig +++ b/app/Resources/views/site/become_member.html.twig @@ -78,7 +78,7 @@ {{ membership_fee_natural_person }}€ TTC / an / pour une personne
- Adhérer en tant que particulier + Adhérer en tant que particulier diff --git a/app/Resources/views/site/company_membership/adhesion_entreprise.html.twig b/app/Resources/views/site/company_membership/adhesion_entreprise.html.twig index 9878df7b2..9dd59c54d 100644 --- a/app/Resources/views/site/company_membership/adhesion_entreprise.html.twig +++ b/app/Resources/views/site/company_membership/adhesion_entreprise.html.twig @@ -13,7 +13,7 @@

Ce formulaire est réservé aux entreprises. Vous êtes un particulier ou un indépendant ? - Retrouvez le formulaire d'adhésion dédié. + Retrouvez le formulaire d'adhésion dédié.

{{ form_start(form) }}
diff --git a/app/Resources/views/site/member/company_public_profile.html.twig b/app/Resources/views/site/member/company_public_profile.html.twig index 77a7fc1a0..3a0772589 100644 --- a/app/Resources/views/site/member/company_public_profile.html.twig +++ b/app/Resources/views/site/member/company_public_profile.html.twig @@ -1,9 +1,5 @@ {% extends ':admin/association/membership:_base.html.twig' %} -{% form_theme form with [ - 'form_theme_errors.html.twig' -] %} - {% block submenu %} {% include ':admin/association/membership:_company_menu.html.twig' with { current: "public_profile" diff --git a/app/config/config.yml b/app/config/config.yml index 5d2572e69..dae0cdd80 100644 --- a/app/config/config.yml +++ b/app/config/config.yml @@ -343,7 +343,7 @@ twig: strict_variables: "%kernel.debug%" globals: photo_storage: '@AppBundle\CFP\PhotoStorage' - form_themes: ['form_theme_help.html.twig'] + form_themes: ['form_theme.html.twig'] ting: connections: diff --git a/app/config/routing/admin.yml b/app/config/routing/admin.yml index 19c0baed8..f7f4a0e30 100644 --- a/app/config/routing/admin.yml +++ b/app/config/routing/admin.yml @@ -21,10 +21,6 @@ admin_login: admin_logout: path: /logout -legacy_inscription: - path: /register - defaults: {_controller: AppBundle:Legacy:register} - admin_password: path: /password defaults: {_controller: AppBundle\Controller\Admin\LostPasswordAction} diff --git a/app/config/routing/site.yml b/app/config/routing/site.yml index f13744fc9..90cbc7c96 100644 --- a/app/config/routing/site.yml +++ b/app/config/routing/site.yml @@ -10,6 +10,12 @@ company_membership: options: sitemap: true +member_membership: + path: /adherer/particulier + defaults: {_controller: AppBundle:MemberShip:member} + options: + sitemap: true + company_membership_payment: path: /adherer/entreprise/paiement-{invoiceNumber}-{token} defaults: {_controller: AppBundle:MemberShip:payment} diff --git a/app/config/services.yml b/app/config/services.yml index a69739745..0466fbab5 100644 --- a/app/config/services.yml +++ b/app/config/services.yml @@ -360,6 +360,9 @@ services: AppBundle\Association\Form\UserEditFormDataFactory: autowire: true + AppBundle\Association\Factory\UserFactory: + autowire: true + AppBundle\Offices\OfficesCollection: autowire: true diff --git a/htdocs/templates/administration/inscription.html b/htdocs/templates/administration/inscription.html deleted file mode 100644 index 6654fad27..000000000 --- a/htdocs/templates/administration/inscription.html +++ /dev/null @@ -1,2 +0,0 @@ -

Formulaire d'incription à l'AFUP

-{include file="formulaire.html"} \ No newline at end of file diff --git a/sources/AppBundle/Association/Factory/UserFactory.php b/sources/AppBundle/Association/Factory/UserFactory.php new file mode 100644 index 000000000..82c50ae0d --- /dev/null +++ b/sources/AppBundle/Association/Factory/UserFactory.php @@ -0,0 +1,22 @@ +setCivility(User::CIVILITE_M) + ->setCountry('FR') + ->setLevel(User::LEVEL_MEMBER) + ->setStatus(User::STATUS_ACTIVE) + ->setDirectoryLevel(User::LEVEL_MEMBER) + ; + } +} diff --git a/sources/AppBundle/Association/Form/NearestOfficeChoiceType.php b/sources/AppBundle/Association/Form/NearestOfficeChoiceType.php new file mode 100644 index 000000000..c7f4ce4ec --- /dev/null +++ b/sources/AppBundle/Association/Form/NearestOfficeChoiceType.php @@ -0,0 +1,29 @@ + '']; + foreach ($officesCollection->getOrderedLabelsByKey() as $key => $label) { + $offices[$label] = $key; + } + + $resolver->setDefaults(['choices' => $offices]); + } + + public function getParent() + { + return ChoiceType::class; + } +} diff --git a/sources/AppBundle/Association/Form/RegisterUserType.php b/sources/AppBundle/Association/Form/RegisterUserType.php new file mode 100644 index 000000000..7c2919bda --- /dev/null +++ b/sources/AppBundle/Association/Form/RegisterUserType.php @@ -0,0 +1,51 @@ +add('userCommonInfo', UserType::class, [ + 'inherit_data' => true, + 'data_class' => User::class, + ]) + ->add('country', CountryType::class, [ + 'label' => 'Pays', + 'required' => true + ]) + ->add('mobilephone', TelType::class, [ + 'label' => 'Portable', + 'required' => false + ]) + ->add('nearestOffice', NearestOfficeChoiceType::class, [ + 'required' => false + ]) + ->add('civility', ChoiceType::class, [ + 'choices' => ['M.' => User::CIVILITE_M, 'Mme' => User::CIVILITE_MME], + 'required' => true + ]) + ; + + $builder->get('userCommonInfo')->add('phone', TextType::class, [ + 'required' => false + ]); + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'data_class' => User::class, + ]); + } +} diff --git a/sources/AppBundle/Association/Model/User.php b/sources/AppBundle/Association/Model/User.php index cb6a20150..15ce9c8b9 100644 --- a/sources/AppBundle/Association/Model/User.php +++ b/sources/AppBundle/Association/Model/User.php @@ -28,6 +28,9 @@ class User implements NotifyPropertyInterface, UserInterface, \Serializable, Not const SLACK_INVITE_STATUS_NONE = 0; const SLACK_INVITE_STATUS_REQUESTED = 1; + const CIVILITE_M = 0; + const CIVILITE_MME = 1; + /** * @var int */ @@ -813,11 +816,13 @@ public function getDirectoryLevel() return $this->levelModules[1]; } - public function setDirectoryLevel($level) + public function setDirectoryLevel($level): self { $oldLevelModules = $this->levelModules; $this->levelModules[1] = $level; $this->propertyChanged('levelModules', $oldLevelModules, $this->levelModules); + + return $this; } public function getWebsiteLevel() diff --git a/sources/AppBundle/Controller/LegacyController.php b/sources/AppBundle/Controller/LegacyController.php index 6c2e81156..319ead1d2 100644 --- a/sources/AppBundle/Controller/LegacyController.php +++ b/sources/AppBundle/Controller/LegacyController.php @@ -4,13 +4,7 @@ namespace AppBundle\Controller; use Afup\Site\Utils\Logs; -use Afup\Site\Utils\Pays; use Afup\Site\Utils\Utils; -use AppBundle\Association\Model\Repository\UserRepository; -use AppBundle\Association\Model\User; -use AppBundle\Association\UserMembership\UserService; -use Exception; -use Smarty; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -69,150 +63,4 @@ public function backOfficeAction(Request $request) 'js' => $js, ]); } - - public function registerAction(Request $request) - { - global $droits; - - $bdd = $GLOBALS['AFUP_DB']; - - $server = $_SERVER; - $_SERVER['REQUEST_URI'] = '/administration/'; - require dirname(__FILE__) . '/../../Afup/Bootstrap/Http.php'; - /** @var Smarty $smarty */ - $userRepository = $this->get(UserRepository::class); - /** @var UserService $userService */ - $userService = $this->get(UserService::class); - $_SERVER = $server; - $droits = Utils::fabriqueDroits($this->get('security.token_storage'), $this->get('security.authorization_checker')); - Logs::initialiser($bdd, $droits->obtenirIdentifiant()); - $pays = new Pays($bdd); - - $formulaire = instancierFormulaire(); - - $formulaire->setDefaults( - [ - 'civilite' => 'M.', - 'id_pays' => 'FR', - 'niveau' => AFUP_DROITS_NIVEAU_MEMBRE, - 'niveau_apero' => AFUP_DROITS_NIVEAU_MEMBRE, - 'niveau_annuaire' => AFUP_DROITS_NIVEAU_MEMBRE, - 'etat' => AFUP_DROITS_ETAT_ACTIF, - ] - ); - - $officesCollection = new \AppBundle\Offices\OfficesCollection(); - $offices = ['' => '-Aucune-']; - foreach ($officesCollection->getOrderedLabelsByKey() as $key => $label) { - $offices[$key] = $label; - } - - $formulaire->addElement('hidden', 'inscription', 1); - $formulaire->addElement('hidden', 'niveau'); - $formulaire->addElement('hidden', 'niveau_apero'); - $formulaire->addElement('hidden', 'niveau_annuaire'); - $formulaire->addElement('hidden', 'etat'); - $formulaire->addElement('hidden', 'compte_svn'); - - $formulaire->addElement('header', '', 'Informations'); - $formulaire->addElement('select', 'civilite', 'Civilité', ['M.', 'Mme']); - $formulaire->addElement('text', 'nom', 'Nom', ['size' => 30, 'maxlength' => 40]); - $formulaire->addElement('text', 'prenom', 'Prénom', ['size' => 30, 'maxlength' => 40]); - $formulaire->addElement('text', 'login', 'Login', ['size' => 30, 'maxlength' => 30]); - $formulaire->addElement('text', 'email', 'Email', ['size' => 30, 'maxlength' => 100]); - $formulaire->addElement('textarea', 'adresse', 'Adresse', ['cols' => 42, 'rows' => 10]); - $formulaire->addElement('text', 'code_postal', 'Code postal', ['size' => 6, 'maxlength' => 10]); - $formulaire->addElement('text', 'ville', 'Ville', ['size' => 30, 'maxlength' => 50]); - $formulaire->addElement('select', 'id_pays', 'Pays', $pays->obtenirPays()); - $formulaire->addElement('text', 'telephone_fixe', 'Tél. fixe', ['size' => 20, 'maxlength' => 20]); - $formulaire->addElement('text', 'telephone_portable', 'Tél. portable', ['size' => 20, 'maxlength' => 20]); - $formulaire->addElement('select', 'nearest_office', 'Antenne la plus proche', $offices); - - $formulaire->addElement('password', 'mot_de_passe', 'Mot de passe', ['size' => 30, 'maxlength' => 30]); - $formulaire->addElement('password', 'confirmation_mot_de_passe', '', ['size' => 30, 'maxlength' => 30]); - $formulaire->addElement('hidden', 'csrf'); // CSRF token - $formulaire->addElement('text', 'lastname', '', ['style' => 'display:none']); // Pot de miel, doit être vide - $formulaire->addElement('header', 'boutons', ''); - $formulaire->addElement('submit', 'soumettre', 'Ajouter'); - - $formulaire->addRule('nom', 'Nom manquant', 'required'); - - // CSRF validation - $lastCsrf = $this->get('session')->get('csrf'); - $formulaire->addRule('csrf', 'csrf validation', 'callback', static function ($value) use ($lastCsrf) { - return $lastCsrf === $value; - }); - - // CSRF generation - $csrf = md5(uniqid(mt_rand(), true)); - $this->get('session')->set('csrf', $csrf); - $formulaire->getElement('csrf')->setValue($csrf); - - $formulaire->addRule('lastname', 'Lastname manquant', 'callback', static function ($value) { - return empty($value); - }); - - $formulaire->addRule('prenom', 'Prénom manquant', 'required'); - $formulaire->addRule('login', 'Login manquant', 'required'); - $formulaire->addRule('login', 'Login déjà existant', 'callback', static function ($value) use ($userRepository) { - return !$userRepository->loginExists($value); - }); - $formulaire->addRule('email', 'Email manquant', 'required'); - $formulaire->addRule('email', 'Email invalide', 'email'); - $formulaire->addRule('adresse', 'Adresse manquante', 'required'); - $formulaire->addRule('code_postal', 'Code postal manquant', 'required'); - $formulaire->addRule('ville', 'Ville manquante', 'required'); - $formulaire->addRule('mot_de_passe', 'Mot de passe manquant', 'required'); - $formulaire->addRule(['mot_de_passe', 'confirmation_mot_de_passe'], 'Le mot de passe et sa confirmation ne concordent pas', 'compare'); - - if ($formulaire->validate()) { - try { - $user = new User(); - $user->setStatus($formulaire->exportValue('etat')); - $user->setUsername($formulaire->exportValue('login')); - $user->setPlainPassword($formulaire->exportValue('mot_de_passe')); - $user->setLevel($formulaire->exportValue('niveau')); - $user->setDirectoryLevel($formulaire->exportValue('niveau_annuaire')); - $user->setWebsiteLevel($formulaire->exportValue('niveau_site')); - $user->setCivility($formulaire->exportValue('civilite')); - $user->setLastName($formulaire->exportValue('nom')); - $user->setFirstName($formulaire->exportValue('prenom')); - $user->setEmail($formulaire->exportValue('email')); - $user->setAddress($formulaire->exportValue('adresse')); - $user->setZipCode($formulaire->exportValue('code_postal')); - $user->setCity($formulaire->exportValue('ville')); - $user->setCountry($formulaire->exportValue('id_pays')); - $user->setPhone($formulaire->exportValue('telephone_fixe')); - $user->setMobilephone($formulaire->exportValue('telephone_portable')); - $user->setNearestOffice($formulaire->exportValue('nearest_office')); - try { - $userRepository->create($user); - Logs::log('Ajout de la personne physique ' . $user->getFirstName() . ' ' . $user->getLastName()); - $userService->sendWelcomeEmail($user); - $this->addFlash('notice', 'Merci pour votre inscription. Il ne reste plus qu\'à régler votre cotisation.'); - - return $this->get('security.authentication.guard_handler') - ->authenticateUserAndHandleSuccess( - $user, - $request, - $this->get(\AppBundle\Security\LegacyAuthenticator::class), - 'legacy_secured_area' - ); - } catch (Exception $e) { - $smarty->assign('erreur', 'Une erreur est survenue lors de la création de votre compte. Veuillez recommencer. Merci.'); - } - } catch (Exception $e) { - $message = sprintf('Une erreur est survenue lors de la création de votre compte (%s). N\'hésitez pas à contacter le bureau via bonjour@afup.org si vous ne comprenez pas l\'erreur en nous précisant le message qui vous est donné. Merci !', $e->getMessage()); - $smarty->assign('erreur', $message); - } - } - - $smarty->assign('formulaire', genererFormulaire($formulaire)); - - return $this->render('admin/base_with_header.html.twig', [ - 'title' => 'Inscription', - 'page' => 'inscription', - 'content' => $smarty->fetch(dirname(__FILE__) . '/../../../htdocs/templates/administration/inscription.html') - ]); - } } diff --git a/sources/AppBundle/Controller/MemberShipController.php b/sources/AppBundle/Controller/MemberShipController.php index 1293e57d3..d85fd8aec 100644 --- a/sources/AppBundle/Controller/MemberShipController.php +++ b/sources/AppBundle/Controller/MemberShipController.php @@ -8,8 +8,10 @@ use Afup\Site\Utils\Utils; use Afup\Site\Utils\Vat; use AppBundle\Association\Event\NewMemberEvent; +use AppBundle\Association\Factory\UserFactory; use AppBundle\Association\Form\CompanyMemberType; use AppBundle\Association\Form\ContactDetailsType; +use AppBundle\Association\Form\RegisterUserType; use AppBundle\Association\Form\UserType; use AppBundle\Association\Model\CompanyMember; use AppBundle\Association\Model\CompanyMemberInvitation; @@ -29,6 +31,7 @@ use AppBundle\LegacyModelFactory; use AppBundle\Payment\PayboxBilling; use AppBundle\Payment\PayboxResponseFactory; +use AppBundle\Security\LegacyAuthenticator; use AppBundle\TechLetter\Model\Repository\SendingRepository; use Assert\Assertion; use Symfony\Component\Finder\Finder; @@ -54,6 +57,38 @@ public function becomeMemberAction() ); } + public function memberAction(Request $request): Response + { + $user = $this->get(UserFactory::class)->createForRegister(); + + $form = $this->createForm(RegisterUserType::class, $user); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + // Nécessaire pour md5 le mdp qui est fait dans le setPlainPassword => a terme, utiliser les cryptages de sf + $user->setPlainPassword($user->getPassword()); + $this->get(UserRepository::class)->save($user); + + Logs::initialiser($GLOBALS['AFUP_DB'], $user->getId()); + Logs::log('Ajout de la personne physique ' . $user->getFirstName() . ' ' . $user->getLastName()); + + $this->get(UserService::class)->sendWelcomeEmail($user); + $this->addFlash('notice', 'Merci pour votre inscription. Il ne reste plus qu\'à régler votre cotisation.'); + + return $this->get('security.authentication.guard_handler') + ->authenticateUserAndHandleSuccess( + $user, + $request, + $this->get(LegacyAuthenticator::class), + 'legacy_secured_area' + ); + } + + return $this->render('admin/association/membership/register.html.twig', [ + 'form' => $form->createView() + ]); + } + public function companyAction(Request $request) { $data = new CompanyMember(); diff --git a/tests/behat/features/PublicSite/Register.feature b/tests/behat/features/PublicSite/Register.feature index 4c805e500..1fd051349 100644 --- a/tests/behat/features/PublicSite/Register.feature +++ b/tests/behat/features/PublicSite/Register.feature @@ -7,18 +7,19 @@ Feature: Site Public - Register When I follow "Adhérer" Then I should see "Devenir membre de l'AFUP" When I follow "Adhérer en tant que particulier" - Then I should see "Formulaire d'incription à l'AFUP" - Then The "civilite" field should only contain the follow values '["M.", "Mme"]' - When I fill in "nom" with "Mon nom" - And I fill in "prenom" with "Mon prénom" - And I fill in "login" with "lelogin" - And I fill in "email" with "registeredUser@gmail.com" - And I fill in "adresse" with "45 rue des Roses" - And I fill in "code_postal" with "69003" - And I fill in "ville" with "LYON" - And I fill in "mot_de_passe" with "test" - And I fill in "confirmation_mot_de_passe" with "test" - And I press "Ajouter" + Then I should see "Formulaire d'inscription à l'AFUP" + Then The "register_user_civility" field should only contain the follow values '["M.", "Mme"]' + When I fill in "register_user_userCommonInfo_lastName" with "Mon nom" + And I fill in "register_user_userCommonInfo_firstName" with "Mon prénom" + And I fill in "register_user_userCommonInfo_username" with "lelogin" + And I fill in "register_user_userCommonInfo_email" with "registeredUser@gmail.com" + And I fill in "register_user_userCommonInfo_address" with "45 rue des Roses" + And I fill in "register_user_userCommonInfo_zipcode" with "69003" + And I fill in "register_user_userCommonInfo_city" with "LYON" + And I fill in "register_user_country" with "FR" + And I fill in "register_user_userCommonInfo_password_first" with "test" + And I fill in "register_user_userCommonInfo_password_second" with "test" + And I press "Créer mon compte" Then I should see "Espace membre" And I should see "Merci pour votre inscription. Il ne reste plus qu'à régler votre cotisation." When I follow "Se mettre à jour"