Bonjour,
Etant débutant en PHP, je me suis un peu cassé la tête à coder (salement je pense) un système de user levels. (donc autant le faire partager!
J'ai développé un petit intranet et outre un niveau admin/user, je voulais faire des niveaux d'utilisateurs customisables pour les différents "modules" de mon site (les pages et groupes de pages) avec des droits d'accès read/write/delete.
après quelques jours d'arrachage de cheveux, j'ai opté pour une méthode simple (qui n'est pas la meilleure j'imagine) mais si ça intéresse quelqu'un, voici le détail (code complet fourni du panneau d'admin etc.) de comment j'ai fait mon truc, je suis d'ailleurs ouvert à tous conseils/critique etc :
un screen du panneau d'admin déjà pour que vous compreniez ce que je veux dire :
1. j'ai crée deux tables dans ma base :
une table contenant les Modules (qui sont tout simplement des pages web en fait, auxquels mes users accèdent, mais chaque module peut être composé de plusieurs pages, comme la page de listing, une page d'ajout etc.), avec un id du module, le nom du module, et les ID des fichiers, correspondant à une variable $id_page = 'x'; sur chaque page PHP (voir plus bas)
exemple de ma table "inv_modules" (je n'ai mis que trpos modules pour l'instant, mais il y en a évidemment un paquet) :
Puis une table contenant les user levels, contenant le user level id, le nom, une description, ainsi que 3 champs, un read, un update et un delete.
pour chaque user level, on a dans chaque liste (read/update/delete) l'ID du module sur lequel on a ces droits
exemple de ma table "user_levels" :
on peut voir par exemple que mon user de "test" n'a les droits de lecture que sur le module d'ID 1 (inventaire serveurs), et aucun autre droits. il ne peut donc que :
- lire & updater les champs du module inventaire serveurs (interdit de supprimer)
- rien faire d'autre sur les autres modules
2. Pour éditer le tout, j'ai crée un petit panneau d'admin qui resemble à ça :
lorsque l'on édite un user level, on modifie ses droits :
on peut aussi modifier les modules directement, ça va de soi :
3. une fois ça fait, j'ai mis, dans mes pages, un ID par page, au top de chaque page j'ai mon header dans lequel j'ai rajouté ces lignes :
Code :
1 2 3 4 5 6 7
|
$page_id = '3'; // ID de la page en question
include ("../../header.php");
include ("../../config/mysqlconn.php");
include ("../../config/functions.php");
list($rights_read, $rights_update, $rights_delete) = CheckProfile($page_id); // fonction de verif et definition des droits
$message = UpdateRights($rights_update); // fonction permettant de désactiver les boutons de mise à jour/modification |
et j'ai donc codé deux petites fonctions pour les droits (dans mes include) :
la première (CheckProfile):
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
/* ------------------------------------- */
/* CheckProfile() */
/* Gestion User Level */
/* ------------------------------------- */
function CheckProfile($page_id) {
// on recupere le user level ID (j'ai une table user avec le userlevel_id spécifié par user, que je met en sessions lors de sa connexion)
$userlevel_id = $_SESSION['level'];
// on recupere les droits de ce user level
$get_rights = 'SELECT * FROM user_levels WHERE user_level_id = "'.$userlevel_id.'"';
$exec_get_rights = mysql_query($get_rights);
while ($data = mysql_fetch_assoc($exec_get_rights)) {
// on cree des tableaux contenant les ID des modules de ce user level
$read = explode(" ", $data['read_modules']);
$update = explode(" ", $data['update_modules']);
$delete = explode(" ", $data['delete_modules']);
}
// on initialise des variables a no
$rights_read = 'no';
$rights_update = 'no';
$rights_delete = 'no';
// on choppe le module_id dans la base correspondant a l'ID de la page actuelle
$query_modidpage = 'SELECT module_id FROM inv_modules WHERE module_files REGEXP "[[:<:]]'.$page_id.'[[:>:]]"';
$exec_modidpage = mysql_query($query_modidpage);
$result_modidpage = mysql_result($exec_modidpage, 0);
// on regarde si le user a accès à ce module avec un quelconque droit
if (in_array($result_modidpage, $read)) {
$rights_read = 'yes';
}
if (in_array($result_modidpage, $update)) {
$rights_update = 'yes';
}
if (in_array($result_modidpage, $delete)) {
$rights_delete = 'yes';
}
// si le user level n'a aucun droit, on exit la page
if (($rights_read == 'no') && ($rights_update == 'no') && ($rights_delete == 'no')) {
echo '<br><font size="2">Your User Level is not authorized to access this page</font><br>';
exit;
}
// on renvoie les 3 variables
return array($rights_read, $rights_update, $rights_delete);
} |
et la seconde (et la troisieme pour le delete) :
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
/* ------------------------------------- */
/* UpdateRights() */
/* Gestion User Level pour les Updates */
/* ------------------------------------- */
function UpdateRights($rights_update) {
if ($rights_update == "no") {
$msg=' DISABLED';
} else {
$msg='';
}
return $msg;
}
/* ------------------------------------- */
/* DeleteRights() */
/* Gestion User Level pour les delete */
/* ------------------------------------- */
function DeleteRights($rights_delete) {
if ($rights_delete == "no") {
echo '<br>Your User level is not authorized to perform deletions in this Module<br>';
exit;
}
} |
et tout marche comme sur des roulettes
pour le code, à chaque emplacement d'un bouton de modification de formulaire par exemple, j'ai mis ça ( ça rajoute un "DISABLED" si la personne n'a pas les droits) :
Code :
1 2
|
echo '<input type="submit" value="Modify" id="submit" '.$message.'> |
je devrais certainement recoder une belle fonction pour que ça gère non seulement les boutons mais aussi le reste (comme pour le delete par exemple, un truc à checked avant une requête MySQL par exemple)
et pour le delete interdit, je rajoute ça :
Code :
1 2
|
DeleteRights($rights_delete); |
juste avant les requêtes de suppression
voilà,
si vous désirez le code du panneau d'admin complet (j'ai passé des heures dessus à cause des checkboxes) , le voici :
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388
|
<?php
// -------------------------------------------------
// Header
// -------------------------------------------------
$page_title = 'User Levels Management (en dev)';
$page_id = '1';
include ("../../header.php");
include ("../../config/mysqlconn.php");
include ("../../config/functions.php");
// -------------------------------------------------
// Check sur le type de profil connecté
// -------------------------------------------------
CheckAdmin();
// -------------------------------------------------
// Code Principal
// -------------------------------------------------
echo '<table border="0" cellpadding="2" cellspacing="1" width="750">';
echo '<tr class="tkt_sectionHeader">';
echo '<td>Menu</td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td>';
echo '[ <b><a href="ges_userlevels.php?register">Modules registry</a></b> ] ';
echo '[ <b><a href="ges_userlevels.php?mgt">User levels Configurator</a></b> ] ';
echo '[ <b><a href="ges_userlevels.php?pageids">Files ID</a></b> ] ';
echo '</td>';
echo '</tr>';
echo '</table>';
// -------------------------------------------------
// Add user level
// -------------------------------------------------
if (isset($_GET['add'])) {
if (isset($_POST['validateuseradd'])) {
extract($_POST);
$req_add = 'INSERT INTO user_levels(user_level_id,
user_level_name,
user_level_desc)
VALUES("",
"'.$name.'",
"'.$description.'")';
if (mysql_query($req_add)) {
echo '<br>User Level successfully added.<br>';
write_history_mysql('[ADMIN] User Level '.$user_level_name.'added');
} else {
echo '<br>Error while adding user level, contact the developer<br>';
}
}
echo '<br>';
echo '<table border="0" cellpadding="2" cellspacing="1" width="450" align="center">';
echo '<form method="post" action="ges_userlevels.php?add">';
echo '<tr class="tkt_sectionHeader">';
echo '<td colspan="2">User Level Add</td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td width="100">';
echo 'Name';
echo '</td>';
echo '<td>';
echo '<input type="text" name="name" value="" size="50">';
echo '</td>';
echo '</tr>';
echo '<tr class="tkt_sectionHeader2">';
echo '<td>';
echo 'Description';
echo '</td>';
echo '<td>';
echo '<input type="text" name="description" value="" size="50">';
echo '</td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td colspan="2" align="center">';
echo '<input type="submit" name="validateuseradd" value="Create">';
echo '</td>';
echo '</tr>';
echo '</form>';
echo '</table>';
}
// -------------------------------------------------
// Register Module
// -------------------------------------------------
if (isset($_GET['register'])) {
if (isset($_POST['validatemoduleadd'])) {
extract($_POST);
$insert_mod = 'INSERT INTO inv_modules(module_id,
module_name,
module_files)
VALUES("",
"'.$module_name.'",
"'.$module_files.'")';
if (mysql_query($insert_mod)) {
write_history_mysql('[ADMIN] Module Registered : '.$module_name.'');
} else {
echo '<br>Error while adding Module, please contact the developer.<br>';
}
}
if (isset($_GET['addmodule'])) {
echo '<br>';
echo '<table border="0" cellpadding="2" cellspacing="1" width="450" align="center">';
echo '<form method="post" action="ges_userlevels.php?register">';
echo '<tr class="tkt_sectionHeader">';
echo '<td colspan="2">Add Module</td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td>Module Name</td>';
echo '<td><input type="text" name="module_name" size="40"></td>';
echo '</tr>';
echo '<tr class="tkt_sectionHeader2">';
echo '<td>Files (IDs, separator: space)</td>';
echo '<td><input type="text" name="module_files" size="40"></td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td colspan="2" align="center"><input type="submit" name="validatemoduleadd" value="Register"></td>';
echo '</tr>';
echo '</form>';
echo '</table>';
echo '<br>';
} else {
echo '<br>';
echo '<center><a href="ges_userlevels.php?register&addmodule">register a module</a></center>';
}
echo '<br>';
echo '<table border="0" cellpadding="2" cellspacing="1" width="750" align="center">';
echo '<tr class="tkt_sectionHeader">';
echo '<td colspan="3">Registered Modules</td>';
echo '</tr>';
echo '<tr class="tkt_sectionHeader">';
echo '<td>Name</td>';
echo '<td>File IDs</td>';
echo '<td align="center">Action</td>';
echo '</tr>';
$all_registered_mods = 'SELECT * FROM inv_modules ORDER BY module_name';
$exec_all_registered_mods = mysql_query($all_registered_mods);
while ($data = mysql_fetch_assoc($exec_all_registered_mods)) {
echo '<tr class="tkt_lightcell">';
echo '<td>';
echo $data['module_name'];
echo '</td>';
echo '<td>';
echo $data['module_files'];
echo '</td>';
echo '<td align="center">';
echo '<a href="ges_userlevels.php?register&mod='.$data['module_id'].'&name='.$data['module_name'].'"><img src="../../images/search.gif" border="0" alt="modifier"></a> ';
echo '<a href="ges_userlevels.php?register&del='.$data['module_id'].'&name='.$data['module_name'].'" OnClick="if (window.confirm(\'Are you sure you want to delete this module ?\')){return true;}else{return false;}"><img src="../../images/suppr.gif" border="0" alt="delete"></a>';
echo '</td>';
echo '</tr>';
}
echo '</table>';
}
// -------------------------------------------------
// Configurator Listing
// -------------------------------------------------
if (isset($_GET['mgt'])) {
echo '<br>';
echo '<center><a href="ges_userlevels.php?add">add a user level</a></center>';
echo '<br>';
echo '<table border="0" cellpadding="2" cellspacing="1" width="450" align="center">';
echo '<tr class="tkt_sectionHeader">';
echo '<td colspan="3">User Levels available</td>';
echo '</tr>';
$userlevels = 'SELECT * FROM user_levels ORDER BY user_level_name';
$exec_userlevels = mysql_query($userlevels);
while ($data = mysql_fetch_assoc($exec_userlevels)) {
echo '<tr class="tkt_lightcell">';
echo '<td>';
echo $data['user_level_name'];
echo '</td>';
echo '<td>';
echo $data['user_level_desc'];
echo '</td>';
echo '<td align="center" width="70">';
echo '<a href="ges_userlevels.php?modify='.$data['user_level_id'].'&name='.$data['user_level_name'].'"><img src="../../images/search.gif" border="0" alt="modifier"></a> ';
echo '<a href="ges_userlevels.php?delete='.$data['user_level_id'].'&name='.$data['user_level_name'].'" OnClick="if (window.confirm(\'Are you sure u wanna delete this userlevel ?\')){return true;}else{return false;}"><img src="../../images/suppr.gif" border="0" alt="delete"></a>';
echo '</td>';
}
echo '</table>';
}
// -------------------------------------------------
// Configurator validation Edition
// -------------------------------------------------
if (isset($_POST['validate_edition'])) {
extract($_POST);
// on reprend les valeurs originales de ce userlevel avec une requete mysql
// (on aurait pu les envoyer dans le formulaire mais bon, j'aime le code sale)
$req_edit = 'SELECT * FROM user_levels WHERE user_level_id = "'.$user_level_id.'"';
$query_edit = mysql_query($req_edit);
while ($data = mysql_fetch_assoc($query_edit)) {
// on split le bazar
$modules_read = explode(" ", $data['read_modules']);
$modules_update = explode(" ", $data['update_modules']);
$modules_delete = explode(" ", $data['delete_modules']);
// pour chaque module existant, on regarde
$req_mods = 'SELECT * FROM inv_modules ORDER BY module_name';
$mods_query = mysql_query($req_mods);
while ($row = mysql_fetch_assoc($mods_query)) {
$module_id = $row['module_id'];
// -----------------------
// READ
// si on a coché le read
if (isset($read[$module_id])) {
if (in_array($row['module_id'], $modules_read)) {
// le module est deja en accès read
$null = 'null';
} else {
// on inscrit le module en accès read (on le rajoute dans le tableau)
$modules_read[] = $row['module_id'];
}
// si le read est décoché
} else {
if (in_array($row['module_id'], $modules_read)) {
// l'accès read à ce module doit etre désactivé (on vide l'entree du tableau)
while(in_array($module_id, $modules_read)) {
$key = array_search($module_id, $modules_read);
unset($modules_read[$key]);
}
} else {
// l'accès à ce module était déjà inactif
$null = 'null';
}
}
// -----------------------
// UPDATE
// si on a coché le update
if (isset($update[$module_id])) {
if (in_array($row['module_id'], $modules_update)) {
// le module est deja en accès update
$null = 'null';
} else {
// on inscrit le module en accès update (on le rajoute dans le tableau)
$modules_update[] = $row['module_id'];
}
// si le update est décoché
} else {
if (in_array($row['module_id'], $modules_update)) {
// l'accès update à ce module doit etre désactivé (on vide l'entree du tableau)
while(in_array($module_id, $modules_update)) {
$keu = array_search($module_id, $modules_update);
unset($modules_update[$keu]);
}
} else {
// l'accès à ce module était déjà inactif
$null = 'null';
}
}
// -----------------------
// DELETE
// si on a coché le delete
if (isset($del[$module_id])) {
if (in_array($row['module_id'], $modules_delete)) {
// le module est deja en accès delete
$null = 'null';
} else {
// on inscrit le module en accès delete (on le rajoute dans le tableau)
$modules_delete[] = $row['module_id'];
}
// si le delete est décoché
} else {
if (in_array($row['module_id'], $modules_delete)) {
// l'accès delete à ce module doit etre désactivé (on vide l'entree du tableau)
while(in_array($module_id, $modules_delete)) {
$ked = array_search($module_id, $modules_delete);
unset($modules_delete[$ked]);
}
} else {
// l'accès à ce module était déjà inactif
$null = 'null';
}
}
}
// on construit une nouvelle variable avec les nouvelles valeurs du tableau
$nouveau_read = implode(" ", $modules_read);
$nouveau_update = implode(" ", $modules_update);
$nouveau_delete = implode(" ", $modules_delete);
// requete de mise a jour de la base de données pour ce user level
$maj_db = 'UPDATE user_levels
SET read_modules = "'.$nouveau_read.'",
update_modules = "'.$nouveau_update.'",
delete_modules = "'.$nouveau_delete.'"
WHERE user_level_id = "'.$user_level_id.'"';
if (mysql_query($maj_db)) {
write_history_mysql('[ADMIN] User Level '.$user_level_name.' updated');
echo '<script language="Javascript">
<!--
document.location.replace("ges_userlevels.php?mgt");
// -->
</script>';
} else {
echo '<br>Error during the update, contact the developer.<br>';
}
}
}
// -------------------------------------------------
// Configurator Edition
// -------------------------------------------------
if (isset($_GET['modify'])) {
$user_level_id = $_GET['modify'];
$user_level_name = $_GET['name'];
echo '<br>';
echo '<table border="0" cellpadding="2" cellspacing="1" width="550" align="center">';
echo '<form method="post" action="ges_userlevels.php">';
echo '<tr class="tkt_sectionHeader">';
echo '<td colspan="4">';
echo 'Editing User Level Rights for : <font size="2" color="red">'.$user_level_name.'</font>';
echo '<input type="hidden" name="user_level_id" value="'.$user_level_id.'">';
echo '<input type="hidden" name="user_level_name" value="'.$user_level_name.'">';
echo '</td>';
echo '</tr>';
echo '<tr class="tkt_sectionHeader">';
echo '<td width="430">Module Name</td>';
echo '<td width="40" align="center">Read</td>';
echo '<td width="40" align="center">Update</td>';
echo '<td width="40" align="center">Delete</td>';
echo '</tr>';
// on récupère les valeurs du user level choisi
$req_edit = 'SELECT * FROM user_levels WHERE user_level_id = "'.$user_level_id.'"';
$query_edit = mysql_query($req_edit);
while ($data = mysql_fetch_assoc($query_edit)) {
// on split les champs pour recuperer les droits de chaque module
$modules_read = explode(" ", $data['read_modules']);
$modules_update = explode(" ", $data['update_modules']);
$modules_delete = explode(" ", $data['delete_modules']);
// on liste tous les modules dispo
$req_mods = 'SELECT * FROM inv_modules ORDER BY module_name';
$mods_query = mysql_query($req_mods);
while ($row = mysql_fetch_assoc($mods_query)) {
// pour chaque module, on regarde si ce module est dans le tableau read, update ou delete pour ce user level
// si c'est le cas, on coche la case, sinon, on ne coche rien
$module_id = $row['module_id'];
//
echo '<tr class="tkt_lightcell">';
// nom
echo '<td width="430">'.$row['module_name'].'</td>';
// read
if (in_array($row['module_id'], $modules_read)) {
echo '<td width="40" align="center"><input type="checkbox" name="read['.$row['module_id'].']" value="" CHECKED></td>';
} else {
echo '<td width="40" align="center"><input type="checkbox" name="read['.$row['module_id'].']" value=""></td>';
}
// update
if (in_array($row['module_id'], $modules_update)) {
echo '<td width="40" align="center"><input type="checkbox" name="update['.$row['module_id'].']" value="" CHECKED></td>';
} else {
echo '<td width="40" align="center"><input type="checkbox" name="update['.$row['module_id'].']" value=""></td>';
}
// delete
if (in_array($row['module_id'], $modules_delete)) {
echo '<td width="40" align="center"><input type="checkbox" name="del['.$row['module_id'].']" value="" CHECKED></td>';
} else {
echo '<td width="40" align="center"><input type="checkbox" name="del['.$row['module_id'].']" value=""></td>';
}
//
echo '</tr>';
}
}
echo '<tr class="tkt_lightcell">';
echo '<td colspan="4" align="center"><input type="submit" name="validate_edition" value="Modify"></td>';
echo '</tr>';
echo '</form>';
echo '</table>';
}
// -------------------------------------------------
// Footer
// -------------------------------------------------
include ("../../footer.php");
?> |
la seule chose "galère", c'est attribuer un ID à chaque page PHP "manuellement" si j'ose dire.
J'ai donc crée un script unix qui me trouve l'ID automatiquement de la prochaine page (et qui s'affiche dans mon interface bien sûr) :
Code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
// -------------------------------------------------
// Files ID
// -------------------------------------------------
if (isset($_GET['pageids'])) {
$last_used_id = exec('find '.$Modsdir.' -type f -exec grep "page_id = " {} \; | awk -F"\"" \'{ print $2 }\' | sort -n | tail -1');
$next_free_id = $last_used_id + 1;
echo '<br>';
echo '<table border="0" cellpadding="2" cellspacing="1" width="450">';
echo '<tr class="tkt_sectionHeader">';
echo '<td colspan="2">Free IDs</td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td>';
echo 'Next Usable Free ID';
echo '</td>';
echo '<td>';
echo $next_free_id;
echo '</td>';
echo '</tr>';
echo '<tr class="tkt_lightcell">';
echo '<td>';
echo 'Line to be added at top of file';
echo '</td>';
echo '<td>';
echo '$page_id = "'.$next_free_id.'";';
echo '</td>';
echo '</tr>';
echo '</table>';
} |
donc quand je crée une page à partir de mon template, je n'ai qu'à définir cette variable en haut de mon code avec l'ID généré
voilà
ps :je suis ouvert à tout conseil / toute critique, soyez indulgents, je débute complètement en PHP, alors je code très salement et n'ai pas toujours les bonnes notions
ps : j'utilise php 5.2.1 mais je pense que le code est générique ? je n'utilise que des choses de base (étant débutant..)