Pages

Date 19 juillet 2013

Jobeet ZF2 - Jour 10 - Utilisateurs et ACL

J'espère que vous avez apprécié le jour 9 et que vous avez eu le temps de souffler un peu.
Aujourd'hui, nous allons encore avoir un peu de travail...et ce n'est pas peu dire.

Pour ce jour 10, nous allons nous intéresser à la gestion des utilisateurs et à la gestion des ACL: nous verrons pour cela de nouveaux modules (ZfcUser et BjyAuthorize).
Nous serons amenés à toucher à la fois au module Front et au module Admin.

Modification du 16/09/2013:
Après plusieurs commentaires m'indiquant un problème avec BjyAuthorize (modification du fichier schema.sql), je vous recommande d'utiliser pour le moment une ancienne version de ce module.

Pour cela, modifier le fichier composer.json:
Chercher la ligne "bjyoungblood/bjy-authorize": "dev-master"
Remplacer-la par "bjyoungblood/bjy-authorize": "1.3.*"
Cela permettra d'utiliser la même version de BjyAuthorize que j'utilise dans ce tuto...

Nous pourrions très bien développer nous-même la gestion des utilisateurs et des droits d'accès (ZF2 fournit des classes pour les ACL), mais il existe des modules (très pratique) qui nous ferons gagner du temps.

Installation des modules ZfcUser et BjyAuthorize

ZfcUser est un module d'enregistrement et d'authentification d'utilisateur pour ZF2. Ce module fonctionne, de base, avec \Zend\Db. Mais il permet aussi d'utiliser d'autres adaptateurs de connexion (ex Doctrine).

BjyAuthorize est un module fournissant une façade pour Zend\Permissions\Acl qui facilitera son utilisation avec des modules et des applications. Par défaut, il offre une configuration simple via des fichiers de configuration ou en utilisant Zend\Db ou Doctrine (via ZfcUserDoctrineORM).


Le module ZfcUser

Commençons par installer le module ZfcUser. Nous allons utiliser composer:
php composer.phar require zf-commons/zfc-user:dev-master

Cette commande va rajouter le module dans composer.json et installer ce nouveau module dans vendor/zf-commons/zfc-user.
En parallèle, le module ZfcBase sera installé: ce module est une dépendance nécessaire pour ZfcUser (et d'autres modules) et contient une suite de classes.

Il faut ensuite déclarer ces deux modules (ZfcBase et ZfcUser) dans notre fichier application.config.php:
return array(
    'modules' => array(
        'BjyProfiler',
        'ZendDeveloperTools',
        'ZfcAdmin',
        'Jobeet',
        'Front',
        'Admin',
        'ZfcBase',
        'ZfcUser',
    ),
    'module_listener_options' => array(
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
        ),
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);

Les données de ZfcUser seront stockées dans notre base de données. Le module fournit les schémas pour différentes base de données. Les scripts sont disponibles dans vendor/zf-commons/zfc-user/data. Nous allons utiliser la version MySQL pour créer la table 'user' qui sera utilisée par ZfcUser:
mysql -u jobeet -p jobeet < schema.mysql.sql

Le module ZfcUser a quelques options qui nous autorise une personnalisation rapide des fonctionnalités principales. Après linstallation du module, copier le fichier vendor/zf-commons/zfc-user/config/zfcuser.global.php.dist vers config/autoload/zfcuser.global.php et modifier les valeurs désirées. Plus d'informations sur ces options sont disponibles sur le compte github du module.

Voici la config de mon fichier zfcuser.global.php:
<?php
$settings = array(
    'zend_db_adapter' => 'Zend\Db\Adapter\Adapter',
    'user_entity_class' => 'ZfcUser\Entity\User',
    'enable_registration' => true,
    'enable_username' => true,
    'auth_adapters' => array( 100 => 'ZfcUser\Authentication\Adapter\Db' ),
    'enable_display_name' => true,
    'auth_identity_fields' => array('email', 'username'),
    'login_form_timeout' => 300,
    'user_form_timeout' => 600,
    'login_after_registration' => false,
    'use_registration_form_captcha' => false,
    'use_redirect_parameter_if_present' => true,

    //'user_login_widget_view_template' => 'zfc-user/user/login.phtml',
    //'login_redirect_route' => 'zfcuser',
    //'logout_redirect_route' => 'zfcuser/login',

    //'password_cost' => 14,
    //'enable_user_state' => true,

    //'default_user_state' => 1,
    //'allowed_login_states' => array( null, 1 ),
    
    'table_name' => 'user',
);

/**
 * You do not need to edit below this line
 */
return array(
    'zfcuser' => $settings,
    'service_manager' => array(
        'aliases' => array(
            'zfcuser_zend_db_adapter' => (isset($settings['zend_db_adapter'])) ? $settings['zend_db_adapter']: 'Zend\Db\Adapter\Adapter',
        ),
    ),
);

Allez voir dans le navigateur jobeet.lxc/user:

Si vous avez un formulaire de connexion: bravo! L'installation et la configuration sont correctes.
Pour le moment, le design n'est pas terrible, mais nous y remédierons plus tard.


Le module BjyAuthorize

Ajoutons maintenant le module BjyAuthorize pour gérer les droits d'accès.
php composer.phar require bjyoungblood/bjy-authorize:1.3.*

Activez le module dans le fichier application.config.php:
<?php

return array(
    'modules' => array(
        'BjyProfiler',
        'ZendDeveloperTools',
        'ZfcAdmin',
        'Jobeet',
        'Front',
        'Admin',
        'ZfcBase',
        'ZfcUser',
        'BjyAuthorize',
    ),
    'module_listener_options' => array(
        'config_glob_paths'    => array(
            'config/autoload/{,*.}{global,local}.php',
        ),
        'module_paths' => array(
            './module',
            './vendor',
        ),
    ),
);

Le module BjyAuthorize fournit, lui-aussi, un fichier SQL à exécuter pour stocker ses données. Le fichier se trouve dans vendor/bjyoungblood/bjy-authorize/data/schema.sql
mysql -u jobeet -p jobeet < schema.sql

Copiez ensuite le fichier vendor/BjyAuthorize/config/module.config.php vers config/autoload/module.bjyauthorize.global.php

Je vous ajoute la configuration de ce fichier.
<?php
<?php
/**
 * BjyAuthorize Module (https://github.com/bjyoungblood/BjyAuthorize)
 *
 * @link https://github.com/bjyoungblood/BjyAuthorize for the canonical source repository
 * @license http://framework.zend.com/license/new-bsd New BSD License
 */
return array(
    'bjyauthorize' => array(
        // default role for unauthenticated users
        'default_role' => 'guest',
        
        // identity provider service name
        'identity_provider' => 'BjyAuthorize\Provider\Identity\ZfcUserZendDb',
        
        // Role providers to be used to load all available roles into Zend\Permissions\Acl\Acl
        // Keys are the provider service names, values are the options to be passed to the provider
        'role_providers' => array(
            'BjyAuthorize\Provider\Role\ZendDb' => array(
                'table' => 'user_role',
                'role_id_field' => 'role_id',
                'parent_role_field' => 'parent'
            )
        ),
        
        // Guard listeners to be attached to the application event manager
        'guards' => array(
            'BjyAuthorize\Guard\Route' => array(
                array('route' => 'zfcadmin', 'roles' => array('admin')),
                array('route' => 'zfcadmin/logout', 'roles' => array('user', 'admin')),
                array('route' => 'zfcadmin/login', 'roles' => array('guest', 'user', 'admin')),
                array('route' => 'zfcadmin/authenticate', 'roles' => array( 'guest', 'user', 'admin')),
                array('route' => 'zfcadmin/register', 'roles' => array('guest')),
                array('route' => 'zfcadmin/category', 'roles' => array('admin')),
                array('route' => 'zfcadmin/category/action', 'roles' => array('admin')),
                array('route' => 'zfcadmin/job', 'roles' => array('admin')),
                array('route' => 'zfcadmin/job/action', 'roles' => array('admin')),
                array('route' => 'home', 'roles' => array('guest', 'user', 'admin')),
                array('route' => 'home/logout', 'roles' => array('user', 'admin')),
                array('route' => 'home/add_job', 'roles' => array('user', 'admin')),
                array('route' => 'home/login', 'roles' => array('guest', 'user', 'admin')),
                array('route' => 'home/authenticate', 'roles' => array('guest', 'user', 'admin')),
                array('route' => 'home/register', 'roles' => array('guest')),
                array('route' => 'home/list_category_page', 'roles' => array('guest', 'user', 'admin')),
                array('route' => 'home/get_job', 'roles' => array('guest', 'user', 'admin'))
            )
        )
    )
);


Dans ce fichier de configuration, nous indiquons les différentes routes ainsi que les rôles permettant d'y accéder.

J'ai aussi inséré quelques données dans la base de données. J'ai inséré 3 rôles et un utilisateur admin (login: admin, password: jobeet):
INSERT INTO `user`('user_id', 'username', 'email', 'display_name', 'password', 'state')
    VALUES (1, 'admin', 'admin@admin.fr', 'Admin', '$2y$14$PScxr/eNq9CLsjWiTogYXeTpoYa3jrO7S3wXyQPm5.AOQA8KQQYdW', null);

INSERT INTO user_role VALUES ('guest', 1, null);
INSERT INTO user_role VALUES ('user', 0, 'guest');
INSERT INTO user_role VALUES ('admin', 0, 'user');

INSERT INTO user_role_linker VALUES (1, 'admin');

Accéder à l'administration sans être connecté (jobeet.lxc/admin):

Nous n'avons plus accès à notre administration: nous avons indiqué qu'il fallait le rôle admin pour accéder à notre route admin...

Allez maintenant sur http://jobeet.lxc/user/login, connectez-vous avec l'utilisateur admin / jobeet (vous serez redirigés sur la page user). Puis retourner sur la page d'administration: vous avez accès à l'administration, car vous êtes connectés avec l'utilisateur admin, qui a le rôle admin.

Cela fonctionne a peu près: nous pouvons nous connecter, accéder ou non à certaines pages...
Mais il serait intéressant de pousser un peu plus la personnalisation.

Personnalisation de ZfcUser / BjyAuthorize

Ce que nous pourrions faire, pour améliorer un peu notre application Jobeet:
  • avoir 2 pages de connexion (1 pour l'admin et 1 pour le front)
  • ne pas être redirigé vers la page 403 lorsque l'on accède à une page nécessitant un rôle particulier (autre que Guest), mais être redirigé vers la bonne page de login (page de login de l'admin si l'on souhaite accéder à une page protégée de l'admin, page de login du front si l'on souhaite accéder à une page protégé du front)
Pour le premier point, c'est assez simple. Je ne rentrerais pas trop dans les détails (vous trouverez les sources dans l'archive à la fin de l'article).
Copiez le répertoire vendor/zf-commons/zfc-user/view/zfc-user dans les répertoires view des modules Admin et Front. Personnalisez ensuite les pages module/Front/view/zfc-user/user/login.phtml et module/Admin/view/zfc-user/user/login.phtml.

Le seconde point m'a posé quelques problèmes. Je voulais que l'appel aux pages protégées des modules Admin et Front redirige sur le formulaire de login du module appelé.
Après quelques recherches et quelques essaies, j'ai finalement trouvé une solution.

Le module BjyAuthorize utilise une classe UnauthorizedStrategy qui gère la redirection vers la page "403 Forbidden : you are not authorized to access ...". Je me suis donc intéressé à cette classe, et je l'ai surchargé dans le module Jobeet.

Modifions d'abord le fichier module.config.php du module Jobeet:
<?php
namespace Jobeet;

return array(
    // On indique ici les routes 'principales' de nos modules et les pages login correspondantes
    __NAMESPACE__ => array(
        'options' => array(
            'routes' => array(
                'backend' => 'zfcadmin',
                'backend-login' => 'zfcadmin/login',
                'frontend' => 'home',
                'frontend-login' => 'home/login'
            )
        )
    ),
    'jobeet' => array(
        'nb_job_by_category' => 10,
        'nb_job_pagination' => 4,
        'job_nb_valid_days' => 30
    ),
    // C'est ici que l'on surcharge la classe UnauthorizedStrategy du module BjyAuthorize
    // Notre classe sera utilisée à la place de celle de BjyAuthorize
    'bjyauthorize' => array(
        'unauthorized_strategy' => 'Jobeet\View\UnauthorizedStrategy'
    ),
    'service_manager' => array(
        'factories' => array(
            'BjyAuthorize\View\UnauthorizedStrategy' => 'Jobeet\View\UnauthorizedStrategy'
        )
    )
);

Maintenant, le code de notre classe UnauthorizedStrategy (module/Jobeet/src/Jobeet/View/UnauthorizedStrategy.php):
<?php
namespace Jobeet\View;

use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\Http\Response as HttpResponse;
use Zend\Mvc\MvcEvent;
use Zend\Stdlib\ResponseInterface as Response;

class UnauthorizedStrategy implements ListenerAggregateInterface
{

    /**
     *
     * @var \Zend\Stdlib\CallbackHandler[]
     */
    protected $listeners = array();

    public function attach(EventManagerInterface $events)
    {
        $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, array(
            $this,
            'onDispatchError'
        ), - 5000);
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }

    public function onDispatchError(MvcEvent $e)
    {
        // Do nothing if the result is a response object
        $result = $e->getResult();
        if ($result instanceof Response) {
            return;
        }
        
        $app = $e->getTarget();
        $serviceManager = $app->getServiceManager();
        
        $router = $e->getRouter();
        $match = $e->getRouteMatch();
        
        $routeName = $match->getMatchedRouteName();
        
        $module = $serviceManager->get('ModuleManager')->getModule('Jobeet');
        
        $adminRoute = $module->getOption('routes.backend');
        $adminLoginRoute = $module->getOption('routes.backend-login');
        
        $frontRoute = $module->getOption('routes.frontend');
        $frontLoginRoute = $module->getOption('routes.frontend-login');
        
        if ($routeName === $adminLoginRoute || $routeName === $frontLoginRoute) {
            return;
        }
        
        if (strpos($routeName, $adminRoute) === 0) {
            $loginRoute = $adminLoginRoute;
        } elseif (strpos($routeName, $frontRoute) === 0) {
            $loginRoute = $frontLoginRoute;
        } else {
            return;
        }
        
        // get url to the zfcuser/login route
        $options['name'] = $loginRoute;
        $url = $router->assemble(array(), $options);
        
        // Work out where were we trying to get to
        $options['name'] = $match->getMatchedRouteName();
        $redirect = $router->assemble($match->getParams(), $options);
        
        // set up response to redirect to login page
        $response = $e->getResponse();
        if (! $response) {
            $response = new HttpResponse();
            $e->setResponse($response);
        }
        $response->getHeaders()->addHeaderLine('Location', $url . '?redirect=' . $redirect);
        $response->setStatusCode(302);
    }
}

Si je n'ai rien oublié, si vous tentez d'accéder à une page nécessitant un rôle particulier (autre que Guest), vous serez redirigé vers une fenêtre de login (front ou admin). Sinon, vous trouverez le code complet dans l'archive en fin d'article :-)


Pour finir

Nous allons terminer ce tutoriel en ajoutant une exigence, que nous n'avions pas prévu précédemment : pour faciliter la navigation, les trois derniers emplois vus par l'utilisateur doivent être affiché avec des liens pour revenir à la page des emplois par la suite.

Pour cela, nous allons voir comment gérer les sessions. Je vais traiter ce point de façon très simple, nous ne devons pas stocker d'autres données. On peut configurer un manager de session, via la configuration mais j'ai fait plus simple...

Dans un premier temps, nous devons stocker les emplois consultés par l'utilisateur. Nous allons donc ajouter le stockage dans le controller Job (dans l'action get):
// module/Front/src/Front/Controller/JobController.php
use Zend\Session\Container; // Déclarer ce namespace

class JobController extends JobeetController
{
    [...]
    public function getAction()
    {
        $id_job = $this->params()->fromRoute('id', null);
        
        if (! is_null($id_job)) {
            $job = $this->jobTable->getJob($id_job);
            $category = $this->categoryTable->getCategoryById($job->id_category);
            
            // Nous créons notre container
            $job_sessions = new Container('jobs');
            
            // et nous enregistrons le job consulté
            if (isset($job_sessions->jobs)) {
                if (!in_array($job->id_job, $job_sessions->jobs)) {
                    array_unshift($job_sessions->jobs, $job->id_job);
                    $job_sessions->jobs = array_slice($job_sessions->jobs, 0, 3);
                }
            } else {
                $job_sessions->jobs = array();
                $job_sessions->jobs[] = $job->id_job;
            }

            return new ViewModel(
                array(
                    'job' => $job,
                    'category' => $category
                )
            );
        } else {
            $this->getResponse()->setStatusCode(404);
            return;
        }
    }
}

Ces 3 jobs devront être visibles dans le layout du front. Nous allons donc modifier le fichier layout.phtml (module/Front/view/layout/layout.phtml): Recherchez la chaîne "Recent viewed jobs" et modifiez le code comme suit
<div id="job_history">Recent viewed jobs:<?php echo $this->jobSessions(); ?></div>

Pour la clarté du code HTML du layout, j'ai créé une aide de vue (pour voir comment faire).
Créons l'aide de vue. Elle doit étendre AbstractHelper et implémenter la méthode __invoke():

// module/Front/src/Front/View/Helper/JobSessions.php
<?php
    namespace Front\View\Helper;

    use \Jobeet\Filter\Slugify as Slugify;
    use Zend\ServiceManager\ServiceLocatorAwareInterface;
    use Zend\Session\Container;
    use Zend\View\Helper\AbstractHelper;
class JobSessions extends AbstractHelper implements ServiceLocatorAwareInterface
    {
        public function __invoke()
        {
            $slug = new Slugify();
            $job_sessions = new Container('jobs');
            
            $html = '';
            if (isset($job_sessions->jobs)) {
                $html .= '<ul>';
                $jobTable = $this->serviceLocator->getServiceLocator()->get('Jobeet\Model\JobTable');

                $getUrl = $this->getView()->plugin('url');

                foreach ($job_sessions->jobs as $key => $idJob) {
                    $currentJob = $jobTable->getJob((int)$idJob);
                    
                    if (!is_null($currentJob))
                    {
                        $url = $getUrl(
                            'home/get_job',
                            array(
                                'company' => $slug->filter($currentJob->company),
                                'position' => $slug->filter($currentJob->position),
                                'location' => $slug->filter($currentJob->location),
                                'id' => $currentJob->id_job
                            ),
                            false,
                            false
                        );
                        
                        $html .= '<li><a href="' . $url . '">' . $currentJob->position . ' - ' . $currentJob->company . '</a></li>';
                    }
                }
                $html .= '<ul>';
            }

            return $html;
        }

        public function setServiceLocator(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator)
        {
            $this->serviceLocator = $serviceLocator;
            return $this;
        }

        public function getServiceLocator()
        {
            return $this->serviceLocator;
        }

    }

Dernière étape: il faut déclarer notre aide de vue comme "invokables" dans le fichier Module.php du module Front
// Méthode à ajouter dans module/Front/Module.php
    public function getViewHelperConfig()
    {
        return array(
            'invokables' => array(
                'jobsessions' => 'Front\View\Helper\JobSessions',
            ),
        );
    }

Naviguez sur le site, consultez quelques offres et vous devriez voir les offres consultées:


Nous en avons fini pour le jour 10. Nous avons vu comment ajouter simplement une authentification et un système de gestion des droits à l'aide des modules ZfcUser et BjyAuthorize. Nous avons aussi vu comment surcharger le comportement du module BjyAuthorize pour rediriger vers la page de login plutot qu'afficher la page 403. Finalement, nous avons traité, brièvement, les sessions. Consulter la documentation officielle pour approfondir les sessions (Session Manager, Container, etc).

Comme d'habitude, vous trouverez le code sur mon compte Github.
Si vous avez des questions sur ce jour 10, n'hésitez pas à poster un commentaire ici, ou sur la communauté ZF2 France sur GooglePlus
36 commentaires:
  1. Bonsoir,

    j'essaie d'intégrer BjyAuthorize et je me suis heurté à un problème : lors de l'enregistrement d'un utilisateur via zfcuser, BjyAuthorize ne devrait pas insérer une ligne dans user_role_linker ?

    comment cela ce passe pour vous ?

    cordialement

    RépondreSupprimer
  2. Oui, c'est un point que je voudrais résoudre aussi (sans utiliser de module tier si possible)...
    Je completerais l'article dès que j'aurais trouver une bonne solution

    Sinon, tu peux regarder ce module https://github.com/darkmatus/roleuserbridge => a priori, ca reglerais le pb

    RépondreSupprimer
    Réponses
    1. Bonjour,

      C'est bien ce qu'il me semblait en feuilletant les sources que je n'arrivais pas à trouver ce qu'il me fallait.

      Du coup, j'ai fait un mapper comme darkmatus mais j'ai préféré binder sur l'event 'register.post' plutôt que de surcharger la classe.

      C'ets bête que ce ne soit pas prévu de base.

      Supprimer
    2. je pense que l'utilisation de l'event est la bonne solution justement :-)

      Supprimer
    3. Bonjour, tout d'abord super tuto !!

      Serait il possible d'avoir un exemple de code de la methode utilisé par Gowser ?

      Merci

      Supprimer
  3. excusez moi d'y revenir encore mais j'ai un serieux probleme au jour 4:

    File:
    C:\wamp\www\zf2-tutorial.com\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php:496
    Message:
    Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Zend\Db\Adapter\Adapter

    comment je regle ce probleme merci

    RépondreSupprimer
    Réponses
    1. Je répond un peu tard, mais tu trouveras une réponse de Fadel dans le jour 4 => http://php-underground.blogspot.com/2012/10/jobeet-zf2-jour-4-controller-et-vue.html?showComment=1375898989284#c4935711804067426710

      Supprimer
    2. Bonjour,

      J'ai le même problème et je n'arrive pas à trouver.

      Merci pour votre réponse.

      Supprimer
    3. La reponse ici :)

      http://php-underground.blogspot.com/2012/10/jobeet-zf2-jour-4-controller-et-vue.html?showComment=1375898989284#c4935711804067426710

      Supprimer
  4. Bonjour,
    Tout d'abord, Merci beaucoup pour cette belle série de tutos , c'est du très bon travail.

    j'ai rencontré quelques petits problèmes avec la partie Gestion des ACL ( dixième tuto).

    1 - Page blanche jusqu'à ce que j'ai changé les noms des colonnes 'roleId' et 'parent_id' par 'role_id' et 'parent' dans la table user_role car j'ai vu qu'ils étaient déclarés comme ceci dans le fichier ZendDB.php (vendor/biyougblood/bjy-autorized/src/BjyAuthoriz/Provider/Role/ ). pourtant à la base j'avais utilisé le fichier sql fournis dans le module (.../data/)....

    2- lors de l'authentification , j'avais une exception "role '3' not found" générée par la classe Registry.php (z**f/library/Zend/Permissions/Acl/Role/*), j'ai donc modifié la colonne 'role_id' de la table user_role_linker en varchar(255) au lieu de int(11) et j'y ai mis 'admin' au lieu de '3' qui est l'ID du role 'admin'... et ça a marché ..


    je voulais savoir si vous avez été confrontés aux mêmes problèmes que moi, et si oui, quelles sont les solutions que vous avez adopté.

    Merci pour vos réponses.

    RépondreSupprimer
    Réponses
    1. Bonjour Youssef, t merci pour ton comm :-)

      1 - Bizarrement, dans la table user_role, j'ai les colonne suivante:
      role_id varchar(255)
      is_default tinyint(1)
      parent varchar(255)
      => ca correspond bien aux changement que tu as fait...J'avais aussi utilisé le fichier .sql présent dans le module BjyAuthorize

      2 - Dans user_role_admin, j'ai bien les valeurs id_user=1 et role_id=admin.
      Je vais vérifié si le module BjyAuthorize n'a pas été mis à jour entre le tuto et maintenant...Je ne me souviens pas avoir modifié ça...

      En tout cas, ta réponse pourra servir si d'autres personnes ont le même problème plus tard.

      Supprimer
    2. Youssef, je confirme qu'il y a eu quelques changements sur le fichier .sql du module BjyAuthorize...
      https://github.com/bjyoungblood/BjyAuthorize/commits/master/data/schema.sql

      Supprimer
  5. Romain, merci pour ta réponse rapide :).

    En effet, en suivant le lien j'ai constaté les modifications apporté au module.


    Par contre , en allant dans le fichier vendor/biyougblood/bjy-autorized/src/BjyAuthoriz/Provider/Role/ZendDb.php je vois que la variable protected $roleIdFieldName est toujours à 'role_id' OR 'role_id' n'existe plus dans la table 'user_role'.

    Je vais regarder ça un peu plus en détail et je referai un Post.

    par ailleurs, est ce que tu as prévu d'autre tutos ou est ce la fin de la série ?

    RépondreSupprimer
  6. BjyAuthorize\Exception\UnAuthorizedException

    File:

    jobeet/vendor/bjyoungblood/bjy-authorize/src/BjyAuthorize/Guard/Route.php:133

    Message:

    You are not authorized to access zfcuser/register

    RépondreSupprimer
  7. A quand un nouveau tuto?????

    RépondreSupprimer
  8. Bonsoir, merci pour ce tuto, cependant j'ai un petit probleme, les options de Zfcuser ne sont pas prise en compte.

    Merci d'avance pour votre aide

    RépondreSupprimer
  9. une absence se fait longue, on attend la suite
    Merci

    RépondreSupprimer
  10. Une partie Internationnalisation serait intéressante pour le Jour 11. ( Avec l'utilisation de Poedit =) pour un gain de temps )

    RépondreSupprimer
    Réponses
    1. La partie Internationnalisation est prevue pour le jour 16...Mais ca peut être plus interessant que le jour 11 (sur les flux, que j'ai commencé).
      Mais je vais changer l'ordre. J'attaquerais le tuto sur l'internationnalisation pour le jour 11 ce soir, en esperant pouvoir le publier rapidement

      Supprimer
  11. et une partie Responsive Design pour le Jour 12

    RépondreSupprimer
    Réponses
    1. Bonjour,

      Il existe deja de nombreuses ressources pour le responsive design. De plus, cela n'a rien a voir avec ZF2 ;-)
      Donc je ne traiterais pas cette partie :-)

      Cordialement,
      Romain

      Supprimer
    2. 2-3 liens:
      http://objetdirect.developpez.com/tutoriels/css/responsive-design/
      http://paulgruson.fr/2013/01/22/responsive-design-10-conseils-pour-reussir/
      http://lehollandaisvolant.net/?d=2012/11/24/20/37/08-css-faire-un-theme-mobile-avec-html5-et-responsive-design

      Supprimer
  12. Bonjour, ai je le droit de modifier directement les fichiers du module de ZfcUser ? (UserController et les vues)

    RépondreSupprimer
    Réponses
    1. Il ne faut JAMAIS modifier directement les fichiers des modules présents dans vendor => en cas de mise a jour du module, tu perdrais tes modifs.
      Si tu veux modifier les vues: il faut copier les vues du module ZfcUser dans ton propre module, (en conservant l'arborescence), et indiquer dans la conf que tu souhaite utiliser tes vues custom Zfcuser. Regarde dans le code, il me semble avoir fait ca pour le module Admin (surcharger ed la vue login), ainsi que dans le module Front il me semble.

      Pour modifier le UserController, il me semble qu'il va te falloir faire ton propre controller (soit un nouveau, soit qui etends ZfcUser\UserController) et indiquer dans la conf de zfcuser du'tiliser ton controller plutot que celui de zfcuser => Je te confirme ça dans la semaine, je n'aurais pas le temps de regarder ce soir

      Supprimer
    2. Pour les vues, tu trouveras des explications sur le wiki du module ZfcUser

      https://github.com/ZF-Commons/ZfcUser/wiki

      Cordialement,
      Romain

      Supprimer
  13. d'accord merci beaucoup.

    Par contre j'ai un problème :
    Lorsque je crée un utilisateur, celui ci est bien enregistré dans la table user. Cependant aucun rôle ne lui ai attribué par défaut. (la ligne dans la table user_role_linker n'est pas créée automatiquement).

    Comment y remédier ? car ça pause un gros problème, si l'utilisateur se connecte alors qu'il n'a pas de role, il ne peux accèder à aucune page.

    RépondreSupprimer
  14. Bonjour,
    je me permet de faire une petite remarque en passant , ça concerne la classe UnauthorizedStrategy.

    j'ai réussi à reproduire le fonctionnement souhaité en utilisant le code présenté plus haut, sauf que lorsque j'essaie d'aller sur une route non existante, j'ai l'erreur suivante :
    Fatal error: Call to a member function getMatchedRouteName() on a non-object in C:\xampp\htdocs\Trilab\test\module\Test\src\Test\View\UnauthorizedStrategy.php on line 50

    ce qui est normale car la variable manipulée à la ligne 50 est null quand la route est inexistante ..

    pour ma part je souhaitais qu'une page d'erreur 404 soit affiché dans ce cas .. j'ai alors mis à la ligne 49 ;
    if(!$match) return ; .

    si ça peut servir à quelqu'un ...

    RépondreSupprimer
    Réponses
    1. Bonjour,

      Merci pour ton commentaire, je corrigerais ça dans le code de la prochaine journée :-)

      Supprimer
  15. Je viens de rechercher une configuration pour utiliser la version 1.4 de BjyAuthorize.
    Voici les modifications que j’ai apportées pour que ça fonctionne :
    1. Dans la table user_role_linker, colonne role_id, il faut indiquer l’id du rôle (colonne id de la table user_role) à la place du label du rôle. Ainsi, sur cet exemple, si admin a pour id 3 dans la table user_role, il faut insérer :
    INSERT INTO user_role_linker VALUES (1, 3);
    On doit pouvoir modifier le type de la colonne role_id mais ce n'est pas indispensable.

    2. Ensuite, pour la configuration de BjyAuthorize dans le fichier config/autoload/module.bjyauthorize.global.php :
    'role_providers' => array(
    'BjyAuthorize\Provider\Role\ZendDb' => array(
    'table' => 'user_role',
    'identifier_field_name' => 'role_id',
    'role_id_field' => 'role_id',
    'parent_role_field' => 'parent_id'
    )
    ),

    3. Enfin, pour la configuration de zfc-user, dans le fichier config/autoload/zfcuser.global.php :
    'use_redirect_parameter_if_present' => true,
    'login_redirect_route' => 'zfcadmin',
    'logout_redirect_route' => 'home/login',

    Il y a peut-être mieux mais chez moi ça fonctionne.

    RépondreSupprimer
  16. J'ai mis pas mal de temps pour comprendre comment le bon formulaire de login se met en place : Romain a passé sous silence l'adaptation qu'il a faite dans Front\Module.
    Dans la méthode onBootstrap(MvcEvent $e) de cette classe, il attache une fonction de rappel (méthode de cette classe Front\Module nommée onDispatch) qui va rajouter le path __DIR__ . '/view' à la pile des TemplatePath de l'application. Cette fonction de rappel étant appelée après le chargement des modules, une fois que la pile de TemplatePath a été constituée en fonction de l'ordre de déclaration des modules dans application.config.php, on est ainsi certain qu'en haut de la pile se trouve le bon chemin pour accéder à zfc-user.
    Attention, si le module Admin est déclaré avant le module Front dans application.config.php, c'est la classe Admin\Module qu'il faudra modifier.

    A noter, Romain, qu'il n'est pas utile de déclarer onBootstrap dans init puisque la méthode onBootstrap est appelée automatiquement après le chargement lorsqu'elle est implémentée.

    En tout cas, merci et bravo pour ce tutoriel.

    RépondreSupprimer
    Réponses
    1. Bonsoir Loguit,
      Merci pour ton commentaire et tes précisions :-)
      Effectivement, le tuto manque un peu d'explication sur ce point. Je te remercie pour l'eclaircissement (en espérant que les lecteurs liront aussi les différents commentaires des articles ^^)

      Pour la méthode onBootstrap, il me semble que j'avais vu ça quelque part. J'en prend note, et je corrigerais ça pour la suite des tutos

      Supprimer
  17. svp j veux savoir comment ajouter le module zfcuser pour chaque module sachant que j'ai 3 modules (Administrateur,camion,chauffeur) et comment je peux rediriger l'utilisateur a chaque login et merci d'avance ;)

    RépondreSupprimer
  18. Bonjour quelqu'un a t-il trouvé une solution pour l'ajout automatique de l'user lors de sa création dans la table role_linker ?

    J'ai essayé d'utiliser https://github.com/darkmatus/roleuserbridge, mais rien n'y fait, rien a changé.

    Merci

    RépondreSupprimer
  19. Bonjour j'essai de suivre le tuto, mais je bloque quand il s'agit de definir la strategie utuliser lors d'un acces sur une page interdite
    j'ai bien cree le fichier module/Application/src/Application/View/UnauthorizedStrategy.php
    j'ai copier coller le code de module/Jobeet/src/Jobeet/View/UnauthorizedStrategy.php
    en cheangeant le namespace a l'interieur du fichier a la place de "namespace Jobeet\View;" j'ai "namespace Application\View;"
    j'ai ajouter dans le tableau des service_manager/factories comme indiquer en mettant
    'BjyAuthorize\View\UnauthorizedStrategy' => 'Application\View\UnauthorizedStrategy'
    j'ai ajouter egalement dans le tableau de bjyauthorize 'unauthorized_strategy' => 'Application\View\UnauthorizedStrategy',
    mais j'ai un message d'erreur qui me dit
    Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Application\View\UnauthorizedStrategy

    RépondreSupprimer