Jump to content

Page based Access control code restructuring


mythri

Recommended Posts

Below is the screenshots and script for user page level access i have used it for one of my old projects. Code is working as it was intended. But it needs to be improvised.

Users table

users.png.7dd7520667b9e01ffe584cf7edac8042.png

pages table , which has all the pages and links

pages.png.8e21fa02c1c9821efb4d4b07a0f9009d.png

Access level table. which has user id from users table and page id from pages table (for which user has access)

access_level.png.5319a19b29b1f031244b63682c14feaf.png

 

Once the user is created, admin gives access to the user on page basis, the permissions.php page looks like this

The modules

s1.thumb.PNG.4a9b112337529d9810328a5e62a59f66.PNG

 

Menus inside the modules

s2.thumb.PNG.3afaa5decc562ca3c2ea41ba146477f8.PNG

 

Pages in each menu

s3.thumb.PNG.8e090fae0fe63a33d43bbb1eaa53d1f4.PNG

 

Here is my code for permission.php

<div id="demo2-html">                    
<ul id="demo2" class="mnav">
	<li><a href="#">Sales</a>
    <ul>
    <li><a href="#">Lead</a>
    <ul>
			<table class="table table-bordered table-striped table-hover">
				
                <?php 
				
				$s1 = mysqli_query($con, "SELECT pages.page_id as pid, pages.code, pages.page, 
									pages.href, access_level.aid, access_level.page_id as pgid, 
									access_level.user_id 
								FROM pages
								LEFT JOIN access_level ON (pages.page_id=access_level.page_id 
									AND access_level.user_id=".$user." 
									) WHERE pages.code='led'") or die(mysqli_error($con));
									
				while($s2 = mysqli_fetch_array($s1)) {  ?>
				<tr><li><td><?php echo $s2['page']; ?>  </td><td><input type="checkbox" name="sn[]" value="<?php echo $s2['pid']; ?>" <?php if($s2['pgid'] === $s2['pid']) echo 'checked="checked"';?> />
                <input type="hidden" value="<?php echo $s2['pid']; ?>" name="page_id[<?php echo $s2['pgid']; ?>]">
                </td></li></tr>
                <?php } ?>
                </table>
				</ul>
			</li>
            
            <li><a href="#">Customer</a>
    <ul>
			
			<table class="table table-bordered table-striped table-hover">
				
                <?php 
				
				$s1 = mysqli_query($con, "SELECT pages.page_id as pid, pages.code, pages.page, 
									pages.href, access_level.aid, access_level.page_id as pgid, 
									access_level.user_id 
								FROM pages
								LEFT JOIN access_level ON (pages.page_id=access_level.page_id 
									AND access_level.user_id=".$user." 
									) WHERE pages.code='cst'") or die(mysqli_error($con));
									
				while($s2 = mysqli_fetch_array($s1)) {  ?>
				<tr><li><td><?php echo $s2['page']; ?>  </td><td><input type="checkbox" name="sn[]" value="<?php echo $s2['pid']; ?>" <?php if($s2['pgid'] === $s2['pid']) echo 'checked="checked"';?> />
                <input type="hidden" value="<?php echo $s2['pid']; ?>" name="page_id[<?php echo $s2['pgid']; ?>]">
                </td></li></tr>
                <?php } ?>
                </table>
				</ul>
			</li>
      //code goes for all the other modules
      
      </ul>
            </li>
            
    
    
</ul>
</div>


<input type="hidden" name="user" value="<?php echo $user; ?>" />
<div class="row" align="center">
<input type="submit" name="submit" class="btn btn-success" value="Save" />
  </form> 



// form Submission

if(isset($_POST['submit']))
{
	$user = $_POST['user'];
	
 $sql = "DELETE FROM access_level WHERE user_id = ".$user."";
 $query = mysqli_query($con, $sql) or die (mysqli_error($con));

foreach($_POST['sn'] as $sn)
{
 $sql = "insert into access_level (page_id, user_id) values (".$sn.", ".$user.")";
 $query = mysqli_query($con, $sql) or die (mysqli_error($con));
}


if($query)
{
header("location:users.php?access=1");	
}

	
}
  

So against each user i am storing all the page ids here. When i edit any of the users, it deletes all the records and again insers new records. Which i feel is not a proper way to do.
And also, if i have 10 users and 100 pages, suppose all the users are having access to all the pages, records in user_access table will be 1000. 

And in codewise also, i am redirecting the user to no_access.php (as below) page if the user do not have access.

<?php
ob_start();
include("connect.php");
include("admin_auth.php"); 
$q1 =  basename($_SERVER['REQUEST_URI'], '?' . $_SERVER['QUERY_STRING']);
$q2 = $_SERVER['REQUEST_URI'];
$var1 = "/".$q1;

$qa_path=explode('/', $q2);

$right_path = $qa_path[2].$var1;

$parsedUrl = parse_url($q2);


$curdir = dirname($_SERVER['REQUEST_URI'])."/";



$m4 = "select p.page_id, p.code, p.page, p.href, al.aid, al.page_id, al.user_id FROM pages p INNER JOIN access_level al ON p.page_id=al.page_id WHERE al.user_id=".$_SESSION['user_id']."";

$m5 = mysqli_query($con, $m4)  or die (mysqli_error($con));


while($nk1 = mysqli_fetch_array($m5)) {
	
	$href1[] = ($nk1['href']); }
	
	
	if(in_array($right_path, $href1)) {

echo "<script type='text/javascript'> document.location = ".BASE_URL."/".$right_path."</script>"; 
}
else
{

echo "<script type='text/javascript'> document.location = '../no_access.php' </script>";
exit();
}	

?>

I need help in improve and better/effective (structural) way to do this both in database and php script. 

Link to comment
Share on other sites

If you don't want to delete everything and recreate permissions then that means you want to delete the ones you don't want and add the new ones that you do. Right?
So do that. Figure out all the pages the user had access to, figure out the pages the user should have access to, figure out what's different between the two, and run the appropriate queries.

For the other question, is giving access to everything a common requirement? Then you could set that up as its own thing: the user has a little flag on their account that says they have access to everything. Then modify your permission checking to account for that flag.
Another idea is to group pages together and grant/revoke access to the groups.
Or you could adopt a sort of tagging system, tagging each page with whatever sounds good, then you grant access based on tags instead of direct pages.

Link to comment
Share on other sites

Its not about recreating everything from scratch. If a user having access for page 1, 2, 3, 4 and after few days i want to revoke the permission for page 3 and give access to only 1, 2 and 4 pages, how to do it? As i could not do that, i am deleting everything and inserting from scratch, instead of this is there any way to add/delete only those pages which is been selected. 

IS there any other way to redirect/hide the page if the user doesn't have access instead of doing 

if(in_array($right_path, $href1)) {

echo "<script type='text/javascript'> document.location = ".BASE_URL."/".$right_path."</script>"; 
}
else
{

echo "<script type='text/javascript'> document.location = '../no_access.php' </script>";
exit();
}	

 

Link to comment
Share on other sites

34 minutes ago, mythri said:

Its not about recreating everything from scratch.

Quote

i am deleting everything and inserting from scratch

 

Quote

instead of this is there any way to add/delete only those pages which is been selected.

You could try, but that would require extra data to be submitted in the form and that means more room for error.

So instead of that, do what I said before: figure out the current list, figure out the new list, and compare the two.

 

Quote

IS there any other way to redirect/hide the page if the user doesn't have access instead of doing

You mean if there's a better way than outputting Javascript? Yes.

Link to comment
Share on other sites

39 minutes ago, mythri said:

echo "<script type='text/javascript'> document.location = ".BASE_URL."/".$right_path."</script>";

the above implies that your page access security is the absence of a redirect to the actual url of a page. this is not secure, since anyone can just directly request the 'rigth path' url.

on each request for a page, the code on that page needs to retrieve the user's permissions and determine what the user can do and see on that page. if a user doesn't have permission to access a page, the content you produce and output on that page would be the unique 'no_access.php' content. if you are not already doing so, the navigation you produce and output on any page would be any common links and only those links that the current user has permission for.

this would probably be a good time to dynamically produce the content and output it using a single physical .php file, rather than to create and maintain complete .php code files for each page.

Link to comment
Share on other sites

@mac_gyver 

Quote

on each request for a page, the code on that page needs to retrieve the user's permissions and determine what the user can do and see on that page. if a user doesn't have permission to access a page, the content you produce and output on that page would be the unique 'no_access.php' content. if you are not already doing so, the navigation you produce and output on any page would be any common links and only those links that the current user has permission for.

Now it is happening exactly like this.

 

Quote

this would probably be a good time to dynamically produce the content and output it using a single physical .php file, rather than to create and maintain complete .php code files for each page

can you please share any tutorials/examples how i can dynamically produce ? 

Link to comment
Share on other sites

1 hour ago, requinix said:

 

You could try, but that would require extra data to be submitted in the form and that means more room for error.

So instead of that, do what I said before: figure out the current list, figure out the new list, and compare the two.

 

You mean if there's a better way than outputting Javascript? Yes.

No i tried it. With the same code above, i used 

header("location:".BASE_URL."/".$right_path);

But page content wont open. it says

Quote

 

This page is not working

localhost redirected you too many times.

 

even i have used exit(); after header(), but it didn't. 

Link to comment
Share on other sites

3 hours ago, mythri said:

Now it is happening exactly like this.

it's not exactly what i wrote. what i wrote does not involve redirecting. if the user has permission to access the page, you just proceed with producing and outputting the expected page. if not, produce and output the no access content.

3 hours ago, mythri said:

can you please share any tutorials/examples how i can dynamically produce ?

this is referred to as a Content Management System (CMS.) you would store the information that's different for each page - title, meta tags, description, content, ... in a database table, using the page id as a reference. when a page gets requested, you would get the page id from the url, query for the matching data, and produce the page.

3 hours ago, mythri said:

localhost redirected you too many times.

i was wondering why you weren't already getting a redirect loop. i'll guess that when using javascript, the browser knows it is already on that url and doesn't do anything, whereas the web server telling the browser to redirect, causes it to go ahead and preform the redirect even if already on that url.

you need to get rid of the redirecting altogether, or at least for the case where the user has permission to access the page.

Edited by mac_gyver
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.