sql >> Database teknologi >  >> RDS >> Mysql

Administration af brugerkonti, roller, tilladelser, godkendelse PHP og MySQL -- Del 5

Dette er del 5 af en serie om, hvordan man opretter et brugerkontiadministrationssystem i PHP. Du kan finde de andre dele her:del1, del2, del 3 og del 4.

Vi afsluttede med at administrere administrative brugerkonti i det sidste afsnit samt roller. I denne del gennemgår vi oprettelse af tilladelser og tildeling og fjernelse af tildeling af tilladelser til brugerroller.

Tildeling af tilladelser til roller

Som jeg sagde i den første del af denne serie, er roller relateret til tilladelser i et Mange-til-mange-forhold. En rolle kan have mange tilladelser, og en tilladelse kan tilhøre mange roller.

Vi har allerede lavet rolletabellen. Nu vil vi oprette en tilladelsestabel til at indeholde tilladelser og en tredje tabel kaldet permission_role til at indeholde oplysninger om forholdet mellem roller og tilladelsestabellen.

Opret de to tabeller for at have følgende egenskaber:

tilladelsestabel:

CREATE TABLE `permissions` (
 `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
 `name` varchar(255) NOT NULL UNIQUE KEY,
 `description` text NOT NULL
)

tilladelsesrolletabel:

CREATE TABLE `permission_role` (
 `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
 `role_id` int(11) NOT NULL,
 `permission_id` int(11) NOT NULL,
 KEY `role_id` (`role_id`),
 KEY `permission_id` (`permission_id`),
 CONSTRAINT `permission_role_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
 CONSTRAINT `permission_role_ibfk_2` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`)
)

I permission_role-tabellen refererer role_id til rolle-id'et i rolletabellen, mens permission_id refererer til tilladelses-id-kolonnen i tilladelsestabellen. For at tildele en tilladelse til en rolle, gør vi det ved blot at indsætte en registrering af det pågældende tilladelses-id mod rolle_id'et i tabellen tilladelses_rolle, og relationen er etableret. Det betyder, at hvis vi vil fjerne tildelingen af ​​denne tilladelse fra den rolle, sletter vi blot posten for det rolle_id mod det pågældende tilladelses_id på denne tilladelses_rolle-tabel.

De sidste to linjer i SQL-forespørgslen ovenfor er begrænsninger, der sikrer, at når en bestemt rolle eller tilladelse slettes, slettes alle poster i tabellen permission_role, der har den pågældende tilladelses id eller det rolle-id, også automatisk af databasen. Vi gør dette, fordi vi ikke ønsker, at tabellen permission_role skal gemme relationsoplysninger om en rolle eller en tilladelse, der ikke længere eksisterer.

Du kan også indstille disse begrænsninger manuelt ved hjælp af PHPMyAdmin:du kan gøre det på grænsefladen blot ved at vælge permission_role-tabellen og gå til Relationel visning> Struktur-fanen og blot udfylde værdierne. Hvis du stadig ikke kan gøre dette, så læg en kommentar nedenfor, så skal jeg prøve at hjælpe dig.

Nu er forholdet sat.

Lad os oprette en side for at tildele tilladelser til en rolle. På vores roleList.php-side viser vi de forskellige roller med en 'tilladelse'-knap ved siden af ​​hver. Ved at klikke på dette link kommer vi til en side kaldet assignPermissions.php. Lad os oprette den fil nu i mappen admin/roller.

assignPermissions.php:

<?php include('../../config.php') ?>
<?php include(ROOT_PATH . '/admin/roles/roleLogic.php') ?>
<?php
  $permissions = getAllPermissions();
  if (isset($_GET['assign_permissions'])) {
    $role_id = $_GET['assign_permissions']; // The ID of the role whose permissions we are changing
    $role_permissions = getRoleAllPermissions($role_id); // Getting all permissions belonging to role

    // array of permissions id belonging to the role
    $r_permissions_id = array_column($role_permissions, "id");
  }
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Admin Area - Assign permissions </title>
  <!-- Bootstrap CSS -->
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
  <!-- Custome styles -->
  <link rel="stylesheet" href="../../static/css/style.css">
</head>
<body>
  <?php include(INCLUDE_PATH . "/layouts/admin_navbar.php") ?>
  <div class="col-md-4 col-md-offset-4">
    <a href="roleList.php" class="btn btn-success">
      <span class="glyphicon glyphicon-chevron-left"></span>
      Roles
    </a>
    <hr>
    <h1 class="text-center">Assign permissions</h1>
    <br />
    <?php if (count($permissions) > 0): ?>
    <form action="assignPermissions.php" method="post">
      <table class="table table-bordered">
        <thead>
          <tr>
            <th>N</th>
            <th>Role name</th>
            <th class="text-center">Status</th>
          </tr>
        </thead>
        <tbody>
          <?php foreach ($permissions as $key => $value): ?>
            <tr class="text-center">
              <td><?php echo $key + 1; ?></td>
              <td><?php echo $value['name']; ?></td>
              <td>
                  <input type="hidden" name="role_id" value="<?php echo $role_id; ?>">
                  <!-- if current permission id is inside role's ids, then check it as already belonging to role -->
                  <?php if (in_array($value['id'], $r_permissions_id)): ?>
                    <input type="checkbox" name="permission[]" value="<?php echo $value['id'] ?>" checked>
                  <?php else: ?>
                    <input type="checkbox" name="permission[]" value="<?php echo $value['id'] ?>" >
                  <?php endif; ?>
              </td>
            </tr>
          <?php endforeach; ?>
          <tr>
            <td colspan="3">
              <button type="submit" name="save_permissions" class="btn btn-block btn-success">Save permissions</button>
            </td>
          </tr>
        </tbody>
      </table>
    </form>
    <?php else: ?>
      <h2 class="text-center">No permissions in database</h2>
    <?php endif; ?>
  </div>
  <?php include(INCLUDE_PATH . "/layouts/footer.php") ?>
</body>
</html>

Hvis du klikker på knappen 'tilladelser' for en rolle, kommer du til denne side. Men lige nu, hvis du klikker på den og kommer til denne assignPermissions.php side, er der en fejlmeddelelse, der siger, at getAllPermissions() funktioner er udefinerede. Før vi tilføjer denne metode, lad os gennemgå, hvordan vi faktisk implementerer denne tildeling og fjernelse af tilladelse i vores PHP-kode.

Når du klikker på knappen 'tilladelser' for en rolle, føres du til siden assignPermissions.php med id'et for den pågældende rolle. Men før vi viser siden tildel tilladelser, bruger vi rolle-id'et til at hente alle tilladelser, der allerede er blevet tildelt den pågældende rolle fra databasen. Og så bringer vi også alle de tilgængelige tilladelser frem i tilladelsestabellen. Nu har vi to arrays af tilladelser:dem, der er blevet tildelt en rolle, og alle de tilladelser, der er tilgængelige i vores database. Én førstnævnte er en delmængde af sidstnævnte.

At tildele en tilladelse til en rolle betyder at tilføje den tilladelse fra den overordnede liste over tilladelser til den matrix af tilladelser, der hører til den pågældende rolle, og gemme hele denne information i tabellen permission_role. Fjernelse af tildelingen af ​​en tilladelse fra en rolle betyder, at du fjerner den pågældende tilladelse fra listen over tilladelser, der hører til den pågældende rolle.

Vores logik er at gå gennem en række af alle de tilgængelige tilladelser fra databasen, og derefter for hver af deres id'er bestemmer vi, om det id allerede er i rækken af ​​id'er for rollens tilladelser. hvis den findes, betyder det, at rollen allerede har den tilladelse, så vi viser den ved siden af ​​et afkrydset afkrydsningsfelt. Hvis det ikke eksisterer, viser vi det ved siden af ​​et umarkeret afkrydsningsfelt.

Når alt er blevet vist, betyder et klik på et afkrydset afkrydsningsfelt at fjerne tildelingen af ​​tilladelsen, mens et klik på et ikke-afkrydset afkrydsningsfelt betyder at tildele tilladelsen til rollen. Når al kontrol og fjernelse af afkrydsning er udført, klikker brugeren derefter på knappen 'Gem tilladelser' under tabellen for at gemme alle de tilladelser, der er blevet markeret til den pågældende rolle.

Lad os tilføje alle disse funktioner til roleLogic.php-filen. De er:

roleLogic.php:

// ... other functions up here ...
  function getAllPermissions(){
    global $conn;
    $sql = "SELECT * FROM permissions";
    $permissions = getMultipleRecords($sql);
    return $permissions;
  }

  function getRoleAllPermissions($role_id){
    global $conn;
    $sql = "SELECT permissions.* FROM permissions
            JOIN permission_role
              ON permissions.id = permission_role.permission_id
            WHERE permission_role.role_id=?";
    $permissions = getMultipleRecords($sql, 'i', [$role_id]);
    return $permissions;
  }

  function saveRolePermissions($permission_ids, $role_id) {
    global $conn;
    $sql = "DELETE FROM permission_role WHERE role_id=?";
    $result = modifyRecord($sql, 'i', [$role_id]);

    if ($result) {
      foreach ($permission_ids as $id) {
        $sql_2 = "INSERT INTO permission_role SET role_id=?, permission_id=?";
        modifyRecord($sql_2, 'ii', [$role_id, $id]);
      }
    }

    $_SESSION['success_msg'] = "Permissions saved";
    header("location: roleList.php");
    exit(0);
  }

Sæt tilladelserne til at fungere

På dette tidspunkt kan vi bestemme, hvad en brugers rolle er, og da rollen er relateret til tilladelser, kan vi derfor også kende deres tilladelser.

Nu vil vi sætte disse tilladelser i gang: det vil sige at sikre, at en administratorbruger kun har tilladelse til at udføre de handlinger, som han har tilladelserne til. Vi vil opnå dette ved hjælp af middleware-funktioner. En middleware er dybest set et stykke kode eller en funktion, der bliver udført, før en handling udføres. Typisk kan denne middleware-funktion ændre handlingens adfærd eller udføre nogle kontroller, der kan ende med at stoppe handlingen helt afhængigt af resultaterne af kontrollen.

For eksempel kan en bruger have tilladelserne create-post, update-post og delete-post. Hvis de er logget ind, og de forsøger at publicere et indlæg, tjekker vores middleware-funktion først, om denne bruger har tilladelsen til at publicere indlæg. Hvis de har denne tilladelse, vil vores middleware-funktion returnere true, og indlægget vil blive offentliggjort. Hvis de mangler tilladelsen til at offentliggøre indlæg, vil vores middleware-funktion omdirigere dem tilbage med en besked, der siger, at de ikke har tilladelse til at offentliggøre indlægget.

Vi vil placere alle vores middleware-funktioner i en enkelt fil kaldet middleware.php. Opret den nu i mappen admin og indsæt denne kode i den:

middleware.php:

<?php

  // if user is NOT logged in, redirect them to login page
  if (!isset($_SESSION['user'])) {
    header("location: " . BASE_URL . "login.php");
  }
  // if user is logged in and this user is NOT an admin user, redirect them to landing page
  if (isset($_SESSION['user']) && is_null($_SESSION['user']['role'])) {
    header("location: " . BASE_URL);
  }
  // checks if logged in admin user can update post
  function canUpdatePost($post_id = null){
    global $conn;

    if(in_array('update-post', $_SESSION['userPermissions'])){
      if ($_SESSION['user']['role'] === "Author") { // author can update only posts that they themselves created
          $sql = "SELECT user_id FROM posts WHERE id=?";
          $post_result = getSingleRecord($sql, 'i', [$post_id]);
          $post_user_id = $post_result['user_id'];

          // if current user is the author of the post, then they can update the post
          if ($post_user_id === $user_id) {
            return true;
          } else { // if post is not created by this author
            return false;
          }
      } else { // if user is not author
        return true;
      }
    } else {
      return false;
    }
  }

  // accepts user id and post id and checks if user can publis/unpublish a post
  function canPublishPost() {
    if(in_array(['permission_name' => 'publish-post'], $_SESSION['userPermissions'])){
      // echo "<pre>"; print_r($_SESSION['userPermissions']); echo "</pre>"; die();
      return true;
    } else {
      return false;
    }
  }

  function canDeletePost() {
    if(in_array('delete-post', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canCreateUser() {
    if(in_array('create-user', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canUpdateUser() {
    if(in_array('update-user', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canDeleteUser() {
    if(in_array('delete-user', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canCreateRole($role_id) {
    if(in_array('create-role', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canUpdateRole($role_id) {
    if(in_array('update-role', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
  function canDeleteRole($user_id, $post_id) {
    if(in_array('delete-role', $_SESSION['userPermissions'])){
      return true;
    } else {
      return false;
    }
  }
?>
"; dø(); returnere sandt; } else { return false; } } funktion canDeletePost() { if(in_array('delete-post', $_SESSION['userPermissions'])){ return true; } else { return false; } } funktion canCreateUser() { if(in_array('create-user', $_SESSION['userPermissions'])){ return true; } else { return false; } } funktion canUpdateUser() { if(in_array('update-user', $_SESSION['userPermissions'])){ return true; } else { return false; } } funktion canDeleteUser() { if(in_array('delete-user', $_SESSION['userPermissions'])){ return true; } else { return false; } } funktion canCreateRole($role_id) { if(in_array('create-role', $_SESSION['userPermissions'])){ return true; } else { return false; } } funktion canUpdateRole($role_id) { if(in_array('update-role', $_SESSION['userPermissions'])){ return true; } else { return false; } } funktion canDeleteRole($user_id, $post_id) { if(in_array('delete-role', $_SESSION['userPermissions'])){ return true; } else { return false; } }?>

Den første if-sætning kontrollerer, om brugeren er logget ind. Hvis brugeren ikke er logget ind, vil de blive omdirigeret til hjemmesiden. Den anden if-sætning kontrollerer, om brugeren er logget ind, og om han/hun har en rolle (er admin). Hvis brugeren viser sig at være logget ind og har en rolle, vil vedkommende få adgang til siden, ellers vil den blive omdirigeret tilbage til startsiden.

I hver fil, hvor du ønsker at begrænse ikke-administratorbrugere i at få adgang, skal du blot inkludere denne middleware.php-fil i den fil. Så alle vores admin-filer, som vi ikke ønsker, at normale brugere skal have adgang til, vil vi inkludere denne fil i dem. Så åbn alle filerne i de to mapper inde i admin-mappen, nemlig:brugere, roller. I hver af filerne skal du tilføje følgende linje lige under include for config.php.

Sådan:

<?php include('../../config.php'); ?>
<?php require_once '../middleware.php'; ?>

Og det vil omdirigere enhver ikke-administratorbruger, der forsøger at besøge siden.

Også i denne middleware.php-fil bruger vi PHP's in_array() til at kontrollere, om den tilladelse, vi tester, er i rækken af ​​denne brugers tilladelser. (Når en admin-bruger logger ind, lægger vi al deres tilladelse i et sessionsvariabelt array kaldet $_SESSION['userPermissions'].) Hvis den aktuelle tilladelse er i rækken af ​​brugerens tilladelser, betyder det, at denne bruger har denne tilladelse og derfor returnerer funktionen sand, ellers returnerer den falsk.

Hvis du nu vil kontrollere, om en bruger har en tilladelse, skal du sige, at en public-post-tilladelse, du skal gøre, er at kalde metoden canPublishPost() sådan her:

<?php if (canPublishPost()): ?>
	<!-- User can publish post. Display publish post button -->
<?php else: ?>
	<!-- User cannot publish post. Do not display publish post button -->
<?php endif ?>

Også som en middleware, før vi opdaterer et indlæg, vil vi først kalde canUpdatePost() middleware-funktionen. Hvis funktionen tjekker og ser, at brugeren ikke har tilladelsen til at opdatere indlægget, vil den returnere falsk, og vi kan derefter omdirigere dem til hjemmesiden med en besked om, at han ikke har tilladelse til at opdatere indlægget. Sådan:

// checks if logged in admin user can update post
function updatePost($post_values){
  global $conn;

  if(canUpdatePost($post_values['id']){
     // proceed to update post
  
  } else {
    // redirect back to homepage with message that says user is not permitted to update post
  }
}

Samme ting for publicering/afpublicering af indlæg:

function togglePublishPost($post_id)
{
	if (!canPublishPost($_SESSION['user']['id'])) {
		// redirect them back to dashboard with the message that they don't have the permission to publish post
	} 
    
    // proceed to publish post

}

Nu står vi tilbage med den sidste del af denne tutorial, som er at opdatere brugerprofilen og også give registrerede brugere mulighed for at slette deres egne konti.

Tak for at følge. Hvis du har noget at sige, så skriv det i kommentarerne.


  1. Sådan bestiller du efter dato i MySQL

  2. Roter/pivot tabel med aggregering i Oracle

  3. Planlagt vedligeholdelse af 24/7 IS-databasen i MS SQL Server

  4. 4 måder at finde rækker, der indeholder store bogstaver i MariaDB