Permissions et rôles dans un espace Admin

Bonjour, Je m'explique, je m'exerce en faisant un espace Admin. Les utilisateurs rentrent bien dans leurs sessions, mais c'est au niveau du menu que ça coince. Le menu ne s'affiche pas comme convenu selon les rôles et les permissions.

Je vous joins les tables créer et les messages d'erreurs qui s'affichent, ainsi que mon code. Merci d'avance et bonne soirée.











class/userManager.php


class userManager {

    private $db;
 
    public function __construct($db) {

        $this->setDb($db);
    }

    public function setDb(PDO $dbh) {

        return $this->db = $dbh;
    }

    public function displayMenu($user_role_id) {

        try {

            $sql = 'SELECT a.name, a.slug
                    FROM user_action AS a
                    INNER JOIN user_permission AS p
                    ON(a.actionID = p.actionID
                    AND p.roleID < ' . $user_role_id . ')';

            $stmnt = $this->db->prepare($sql);
            $stmnt->execute();

            while($row = $stmnt->fetch(PDO::FETCH_ASSOC)) {

                $menu_data[] = $row;
            }

            if(isset($menu_data)) {

                return $menu_data;
            }
            else {

                return false;
            }
        }
        catch(PDOException $e) {

            echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
            Message d\'erreur : ' . $e->getMessage();
        }
    }

    public function checkUserPermission($user_role_id, $action_slug) {

        try {
        
            $sql = 'SELECT p.roleID, p.actionID
                    FROM user_permission as p
                    INNER JOIN user_action as a
                    ON(a.slug = "' . $action_slug . '"
                    AND p.actionID = a.actionID)';

            $stmnt = $this->db->prepare($sql);
            $stmnt->execute();

            $row = $stmnt->fetch();

            if($row['p.roleID'] > $user_role_id) {

                return false;
            }
            else {

                return true;
            }
        }
        catch(PDOException $e) {

            echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
            Message d\'erreur : ' . $e->getMessage();
        }

    }
}



process/process-display-menu.php


$manager = new userManager($db);
$menu_items = $manager->displayMenu($_SESSION['level']);
$menu_html = '';

foreach($menu_items as $menu_item) {

    $name = $menu_item['name'];
    $slug = $menu_item['slug'];

    $menu_html .= '<li><a href="' . $slug . '.php">' . $name . '</a></li>' . "\n";
}



process/process-user-permission.php


$action_slug = substr($filename, 0, 4);

$manager = new userManager($db);
$userPermission = $manager->checkUserPermission($_SESSION['level'], $action_slug);

if($userPermission === false) {

    echo 'Erreur. Cette page n\'existe pas.';

    exit;
}



admin/menu.php


require('../process/process-display-menu.php');




<ul class="menu">
    <?php echo $menu_html; ?>
    <li><a href="../index.php">Site web</a></li>
    <li><a href="logout.php">Déconnexion</a></li>
</ul>



Configuration: Windows / Chrome 99.0.4844.82

15 réponses

  1. Modérateur
    Bonjour,

    Visiblement il y a un souci actuellement sur l'affichage des images...

    Ne pourrais tu pas nous copier/coller le message d'erreur directement dans la discussion ?
    0
    1. Remarque : Index indéfini : niveau dans C:\wamp64\www\projet-images-en-poo-et-pdo\process\process-user-permission.php à la ligne 7

      Remarque : Essayer d'accéder à l'offset du tableau sur une valeur de type bool dans C:\wamp64\www\projet-images-en-poo-et-pdo\class\userManager.php à la ligne 301

      Remarque : Index indéfini : niveau dans C:\wamp64\www\projet-images-en-poo-et-pdo\process\process-display-menu.php à la ligne 5

      Une erreur se produit lors de la récupération d'une des données dans la base.
      Message d'erreur : SQLSTATE[42000] : Erreur de syntaxe ou violation d'accès : 1064 Erreur de syntaxe près de ')' à la ligne 5

      Attention : Argument invalide fourni pour foreach() dans C:\wamp64\www\projet-images-en-poo-et-pdo\process\process-display-menu.php à la ligne 8
      0
    2. Bonjour, je n'ai plus que ces messages => Notice: Trying to access array offset on value of type bool in C:\wamp64\www\projet-images-en-poo-et-pdo\class\userManager.php on line 301

      Une erreur est survenue lors de la récupération d'une des données dans la base.
      Message d'erreur : SQLSTATE[42000]: Syntax error or access violation: 1064 Erreur de syntaxe près de ')' à la ligne 5

      Warning: Invalid argument supplied for foreach() in C:\wamp64\www\projet-images-en-poo-et-pdo\process\process-display-menu.php on line 10
      0
      1. Bonjour,

        Le deuxième message indique que tu as une erreur de syntaxe sql dans ta requête, il faudrait afficher cette requête pour vérifier qu'elle est correcte.
        A ce sujet, tu utilises une requête préparée mais sans paramètre, tu concatènes directement la variable $action_slug dans la requête sql, ce qui n'est pas recommandée car tu risques d'avoir des erreurs sql et il y a aussi un risque d'avoir des injections sql. Le mieux serait d'utiliser correctement un paramètre pour ta requête préparée : https://www.php.net/manual/fr/pdo.prepared-statements.php
        0
        1. Modérateur
          Bonjour
          Tu as un message d'erreur sur ta requête car la variable que tu essayes de lui mettre n'est pas bonne...
          Cela est dû à ta première erreur....
          Tu ne récupère visiblement toujours pas la variable de la bonne façon...
          Mais pour qu'on puisse t'aider, il faudrait nous montrer le code tel que tu l'as modifié...
          0
          1. j'ai plus que ceci =>

            Notice: Trying to access array offset on value of type bool in C:\wamp64\www\projet-images-en-poo-et-pdo\class\userManager.php on line 308

            Code modifié =>

            
            public function displayMenu($user_role_id) {
            
                    try {
            
                        $sql = 'SELECT a.name, a.slug
                                FROM user_action AS a
                                INNER JOIN user_permission AS p
                                INNER JOIN user_role AS r
                                ON(a.actionID = p.actionID
                                AND p.roleID < r.level)';
            
                        $stmnt = $this->db->prepare($sql);
                        $stmnt->execute(array(
            
                            ':r.level' => $user_role_id                    
                        ));
            
                        while($row = $stmnt->fetch(PDO::FETCH_ASSOC)) {
            
                            $menu_data[] = $row;
                        }
            
                        if(isset($menu_data)) {
            
                            return $menu_data;
                        }
                        else {
            
                            return false;
                        }
                    }
                    catch(PDOException $e) {
            
                        echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
                        Message d\'erreur : ' . $e->getMessage();
                    }
                }
            
                public function checkUserPermission($user_role_id, $action_slug) {
            
                    try {
                    
                        $sql = 'SELECT p.roleID, p.actionID
                                FROM user_permission AS p
                                INNER JOIN user_action AS a
                                ON(a.slug = p.actionID
                                AND p.actionID = a.actionID)';
            
                        $stmnt = $this->db->prepare($sql);
                        $stmnt->execute(array(
            
                            ':p.actionID' => $action_slug
                        ));
            
                        $row = $stmnt->fetch(PDO::FETCH_ASSOC);
            
                        if($row['p.roleID'] > $user_role_id) {
            
                            return false;
                        }
                        else {
            
                            return true;
                        }
                    }
                    catch(PDOException $e) {
            
                        echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
                        Message d\'erreur : ' . $e->getMessage();
                    }
            
                }
            
            


            
            $level = isset($_SESSION['level']) ? $_SESSION['level'] : NULL;
            
            $manager = new userManager($db);
            $menu_items = $manager->displayMenu($level);
            $menu_html = '';
            
            foreach($menu_items as $menu_item) {
            
                $name = $menu_item['name'];
                $slug = $menu_item['slug'];
            
                $menu_html .= '<li><a href="' . $slug . '.php">' . $name . '</a></li>' . "\n";
            }
            
            


            
            $action_slug = substr($filename, 0, 4);
            
            $level = isset($_SESSION['level']) ? $_SESSION['level'] : NULL;
            
            $manager = new userManager($db);
            $userPermission = $manager->checkUserPermission($level, $action_slug);
            
            if($userPermission === false) {
            
                echo 'Erreur. Cette page n\'existe pas.';
            
                exit;
            }
            
            
            0
            1. Modérateur
              Qu'elle est la ligne qui correspond à la 308 du fichier C:\wamp64\www\projet-images-en-poo-et-pdo\class\userManager ?

              Es-tu sûr que ta variable contient bien la connexion à la bdd

              Et puis.. modifies tes requêtes comme ceci:
                  $sql = 'SELECT a.name, a.slug
                                  FROM user_action a
                                  INNER JOIN user_permission p -- Tu n'as pas de ON pour ta jointure ici ?? --
                                  INNER JOIN user_role r  ON a.actionID = p.actionID
                                  WHERE p.roleID < :user_role_id';
              
                          $stmnt = $this->db->prepare($sql);
                          $stmnt->execute([':user_role_id' => $user_role_id]);
              
              


              
                          $sql = 'SELECT p.roleID, p.actionID
                                  FROM user_permission p
                                  INNER JOIN user_action  a  ON  p.actionID = a.actionID
                                  WHERE a.slug = :action_slug';
              
                          $stmnt = $this->db->prepare($sql);
                          $stmnt->execute([':action_slug'=>$action_slug]);
              
              0
          2. Bonjour, j'ai fait comme tu m'as dit et j'ai toujours l'erreur à ligne 308

            if($row['p.roleID'] > $user_role_id)
            0
            1. Modérateur
              Ce n'est pas
              $row['p.roleID'] 
              

              mais juste
              $row['roleID'] 
              
              0
          3. ça ne marche toujours pas
            0
            1. Modérateur
              Je le répète
              Quand tu dis ça ne marche pas.... Hé bien... ça ne nous aide pas à savoir ce qui bloque. !!

              Pour pouvoir te répondre,
              Il nous faut
              - Le message d'erreur (si il y en a un) tel qu'il est affiché..
              - Le code concerné ( COMPLET )
              - La description de ce qui ne fonctionne pas

              N'hésite pas non plus, dans ton code, à y mettre des var_dump de tes variables pour savoir ce qu'elles contiennent....
              0
          4. J'ai de nouveau modifié mon code et je n'ai plus de messages d'erreurs, par contre çà m'affiche => Erreur. Cette page n'existe pas.

            Voici mon code =>

            
            public function displayMenu($user_role_id) {
            
                    try {
            
                        $sql = 'SELECT a.name, a.slug
                                FROM user_action AS a
                                INNER JOIN user_permission AS p
                                ON a.actionID = p.actionID
                                WHERE p.roleID < :user_role_id';
            
                        $stmnt = $this->db->prepare($sql);
                        $stmnt->execute(array(
            
                            ':user_role_id' => $user_role_id                    
                        ));
            
                        while($row = $stmnt->fetch(PDO::FETCH_ASSOC)) {
            
                            $menu_data[] = $row;
                        }
            
                        if(isset($menu_data)) {
            
                            return $menu_data;
                        }
                        else {
            
                            return false;
                        }
                    }
                    catch(PDOException $e) {
            
                        echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
                        Message d\'erreur : ' . $e->getMessage();
                    }
                }
            
                public function checkUserPermission($user_role_id, $action_slug) {
            
                    try {
                    
                        $sql = 'SELECT p.roleID, p.actionID
                                FROM user_permission AS p
                                INNER JOIN user_action AS a
                                ON p.actionID = a.actionID
                                INNER JOIN user_role AS r
                                ON p.roleID > :user_role_id
                                WHERE a.slug = :action_slug';
            
                        $stmnt = $this->db->prepare($sql);
                        $stmnt->execute(array(
            
                            ':user_role_id' => $user_role_id,
                            ':action_slug' => $action_slug
                        ));
            
                        if($stmnt->fetch(PDO::FETCH_ASSOC)) {
            
                            return true;
                        }
                        else {
            
                            return false;
                        }
                    }
                    catch(PDOException $e) {
            
                        echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
                        Message d\'erreur : ' . $e->getMessage();
                    }
            
                }
            


            
            $level = isset($_SESSION['level']) ? $_SESSION['level'] : NULL;
            
            $manager = new userManager($db);
            $menu_items = $manager->displayMenu($level);
            $menu_html = '';
            
            foreach($menu_items as $menu_item) {
            
                $name = $menu_item['name'];
                $slug = $menu_item['slug'];
            
                $menu_html .= '<li><a href="' . $slug . '.php">' . $name . '</a></li>' . "\n";
            }
            
            


            
            $action_slug = substr($filename, 0, 4);
            
            $level = isset($_SESSION['level']) ? $_SESSION['level'] : NULL;
            
            $manager = new userManager($db);
            $userPermission = $manager->checkUserPermission($level, $action_slug);
            
            if($userPermission === false) {
            
                echo 'Erreur. Cette page n\'existe pas.';
            
                exit;
            }
            
            


            
            require('../process/process-display-menu.php');
            
            


            
            <ul class="menu">
                <?php echo $menu_html; ?>
                <li><a href="../index.php">Site web</a></li>
                <li><a href="logout.php">Déconnexion</a></li>
            </ul>
            
            


            admin/index.php

            
            require('../include/inc-connexion.php');
            require('../class/userManager.php');
            
            $filename = basename( __FILE__ );
            require('../process/process-user-permission.php');
            
            require('menu.php');
            
            
            0
            1. Modérateur
              Ce qui indique donc que tu entres dans le IF
              if($userPermission === false) {
              
                  echo 'Erreur. Cette page n\'existe pas.';
              
                  exit;
              }
              

              et par conséquent, que ta variable $userPermission ne contient rien..

              ce qui semble logique quand on regarde ta requête
              SELECT p.roleID, p.actionID
                                  FROM user_permission AS p
                                  INNER JOIN user_action AS a
                                  ON p.actionID = a.actionID
                                  INNER JOIN user_role AS r
                                  ON p.roleID > :user_role_id
                                  WHERE a.slug = :action_slug
              


              L'as tu testé ??? ( en remplaçant les variables par de "vraies" valeurs bien entendu ) ???
              Et je peux déjà te dire que ta seconde jointure ( le ON ) .. n'est pas bon !!!
              Connais tu le SQL ?? Sais tu faire des jointures ?? ( on peut en douter un peu quand on lit tes codes...)
              Il serait pas mal de te former un minimum avant de te lancer dans l'écriture du code.. sinon ça va vite devenir compliqué.
              0
          5. Bonjour, j'ai de nouveau modifié mon code et je n'ai plus de messages d'erreurs sur la page admin/index.php, par contre

            la variable $menu_html m'affiche pas les liens vers les pages autorisées. J'ai seulement les liens Site Web & Déconnexion.

            Voici mon code modifié :

            
            public function displayMenu($user_role_id) {
            
                    try {
            
                        $sql = 'SELECT a.name, a.slug
                                FROM user_action AS a
                                INNER JOIN user_permission AS p
                                ON a.actionID = p.actionID
                                WHERE p.roleID < :user_role_id';
            
                        $stmnt = $this->db->prepare($sql);
                        $stmnt->execute(array(
            
                            ':user_role_id' => $user_role_id                    
                        ));
            
                        while($row = $stmnt->fetch(PDO::FETCH_ASSOC)) {
            
                            $menu_data[] = $row;
                        }
            
                        if(isset($menu_data)) {
            
                            return $menu_data;
                        }
                        else {
            
                            return false;
                        }
                    }
                    catch(PDOException $e) {
            
                        echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
                        Message d\'erreur : ' . $e->getMessage();
                    }
                }
            
                public function checkUserPermission($action_slug, $user_role_id) {
            
                    try {
                    
                        $sql = 'SELECT p.actionID, p.roleID
                                FROM user_permission AS p
                                INNER JOIN user_action AS a
                                ON p.actionID = a.actionID
                                WHERE a.slug = :action_slug';
            
                        $stmnt = $this->db->prepare($sql);
                        $stmnt->execute(array(
            
                            ':action_slug' => $action_slug
                        ));
            
                        while($row = $stmnt->fetch(PDO::FETCH_ASSOC)) {
            
                            if($row['p.roleID'] > $user_role_id) {
            
                                return false;
                            }
                            else {
            
                                return true;
                            }
                        }
                    }
                    catch(PDOException $e) {
            
                        echo 'Une erreur est survenue lors de la récupération d\'une des données dans la base.<br>
                        Message d\'erreur : ' . $e->getMessage();
                    }
            
                }
            
            


            
            $level = isset($_SESSION['level']) ? $_SESSION['level'] : NULL;
            
            $manager = new userManager($db);
            $menu_items = $manager->displayMenu($level);
            $menu_html = '';
            
            if(!empty($menu_items)) {
            
                foreach($menu_items as $menu_item) {
            
                    $name = $menu_item['name'];
                    $slug = $menu_item['slug'];
            
                    $menu_html .= '<li><a href="' . $slug . '.php">' . $name . '</a></li>' . "\n";
                }
            }
            
            
            0
            1. Modérateur
              Tu as testé ta requête en DIRECTE dans ta BDD ???
              Elle te retourne ce que tu veux ??
              0
          6. Elle me retourne admin/index.php
            0
            1. Modérateur
              et c'est ce que tu veux ??
              0
          7. si je fais ça =>

            
            SELECT a.name, a.slug
                                FROM user_action AS a
                                INNER JOIN user_permission AS p
                                ON a.actionID = p.actionID
                                INNER JOIN user_role AS r
                                WHERE p.roleID = r.roleID;
            

            0
            1. Modérateur
              Et cette requête n'est pas celle que tu as utilisé dans ton code non ??
              0
          8. Je viens de l'introduire dans mon code & ça m'affiche çà =>
            0
            1. Modérateur
              Tu viens de l'introduire ....... ..... QUOI ??? ( la requête ? )
              Où ?? ( à la place de l'autre ? )
              Tu penses à nous montrer ton code tel qu'il est maintenant ?
              0
          9. Ma table user

            mysql> SELECT * FROM user;
            +--------+----------+--------------------------------------------------------------+---------+
            | userID | username | userpass | role_id |
            +--------+----------+--------------------------------------------------------------+---------+
            | 1 | Cyrille | $2y$10$xBhcc4ChC0Vp6hOCNeDE4u0moFfNvVX0fBuxs70VulLehQV7VfOkO | 3 |
            | 2 | Yann | $2y$10$M0rmXEEWw40/bor4bp.E2euu4laF5zLRWUDW5jqJpBx2Bm8Gpn8J6 | 2 |
            | 3 | aucun | $2y$10$HUweFwvOtSi/gFqINcA6h.FSTGZ7O.QFs279C5AGWj3pjKgmj1Ygm | 1 |
            +--------+----------+--------------------------------------------------------------+---------+
            3 rows in set (0.00 sec)

            ma table user_action

            mysql> SELECT * FROM user_action;
            +----------+--------------+----------------+
            | actionID | name | slug |
            +----------+--------------+----------------+
            | 1 | Accueil | index |
            | 2 | Images | create-image |
            | 3 | Images | update-image |
            | 4 | Images | delete-image |
            | 5 | Utilisateurs | account-create |
            +----------+--------------+----------------+
            5 rows in set (0.00 sec)

            ma table user_permission

            mysql> SELECT * FROM user_permission;
            +--------------+----------+--------+
            | permissionID | actionID | roleID |
            +--------------+----------+--------+
            | 1 | 1 | 1 |
            | 2 | 2 | 2 |
            | 3 | 3 | 2 |
            | 4 | 4 | 2 |
            | 5 | 5 | 3 |
            +--------------+----------+--------+
            5 rows in set (0.00 sec)

            ma table user_role

            mysql> SELECT * FROM user_role;
            +--------+----------------+-------+
            | roleID | name | level |
            +--------+----------------+-------+
            | 1 | aucun | 0 |
            | 2 | Editeur | 1 |
            | 3 | Administrateur | 2 |
            +--------+----------------+-------+
            3 rows in set (0.00 sec)
            0
            1. C'est la requête que j'ai introduit.
              0
              1. Modérateur
                que tu as introduit OU ?????
                Dans ton code ????
                Et donc.. à quoi ressemble ton code désormais ????

                Et puis... Pour chaque "JOIN" il te faut un ON

                Et ensuite.. un WHERE pour filtrer sur le champ RoleID par exemple avec l' ID de l'utilisateur que tu lui envois en paramètre de ta fonction...

                Mais avant de te repencher sur le code PHP ... assures toi déjà d'avoir une requête SQL conforme à ce que tu veux obtenir...
                Seulement après tu pour l'introduire... dans ton code php ..!
                0