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. 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
  2. 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. 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
    2. 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
    3. Elle me retourne admin/index.php
      0
      1. Modérateur
        et c'est ce que tu veux ??
        0
    4. 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
    5. 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
    6. ç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
    7. 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
    8. 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
    9. 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. 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. 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. 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. 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