• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 988
  • Last Modified:

Best way to create Coldfusion App user permission system

I have a small contact management system built with 10 different user types.  Each user type has different access to different pages and different items on the pages.  Right now I am taking care of permissions by changing them on each individual page.  This really sucks when I have to add a new User Type and have to go through and grant or deny access on each page.  What I want to do is create a decent permission system to automate the process and make it much easier to add users or change current permissions without having to open each page and do it manually.  Can anyone point me in the right direction on this?  I want to be able to assign users access to specific sections and specific sub-sections in the app.  Any help / advice is very much appreciated.   I'm running CF 8 on a Oracle 10g database.
3 Solutions
What you could do is setup a table of UserRoles.  This equates to the different access rights you're currently hardcoding.  Then use a combination of cflogin, IsUserInRole(), GetUserRoles(), etc, to control the page and item access.


I think you need an extra level.
Perhaps with these 4 tables:    Users,  User Types,   Features   and  UserTypeFeatures.

Users - the table holding the current user information.

User Types - the type of user.   Examples:   manager, admin, read-only, contributor

Features - defines page/field level control to the application.   A feature could be "Add User" or "Create Newsletter"  or "Edit Credit Cards"

UserTypeFeatures - a table which joins the above two tables.  This defines what features are available to what users types.    For example:  Manager has features : add user, create newsletter.   The Admin has Edit Credit Cards, Add users, etc.

userType_Id and Feature_ID

As you develop, you can create "Features"   each feature is associated with a capability that you turn ON or OFF in your code.  For example, if you want to limit the ability to get to a page where you can credit an order, create a feature called "Credit Order" and in your code test to see if this feature is associated with the current user's type.  If it is, allow them in, otherwise, don't.   Your code is only testing for the existance of the feature "Create Order" (perhaps feature ID 123).   Your code doesn't care about user types.

In the admin, you can easily setup a new user type and check off each feature this user type has.
When the user logs in, use thier userType_ID to pull all the associated feature_IDs.   Then have your code test for the needed feature_ID in the various pages.

User Types as you describe are usually called roles&
What you need is below you may have some but I am just going to go thru the basics.


Cross Reference Tables

The User table holds the user specific information like login, name, etc.  

The Role table is where you create the different roles like Admin, Guest, User, Customer, SuperUser, PayRoll, HR, IT, VIP, Management, or whatever fits your application.

The Page table holds the Name of the Page and an ID it can have more if you need or want.

The Section table holds the names of the different types of sections and if you need each section that is unique.

Now the Cross Reference Tables simply hold the ID for the two tables they cross reference.  Example: (user_role table has the User ID and the Role ID)

Now what you can do is when they login setup a session variable that lists all of the pages they have access too and a session variable that lists all of the sections they have access too.

Session.AccessPages =List
Session.AccessSections =List

Then before showing a link to a page see if the user has the id for the page in the Session.AccessPages.  Or if they somehow get a link to a page they are not allowed to simply check to see at the top of the page if they have access to the page ID for this page in there Session.AccessPages.

When you are displaying a page they have access to that has a section they do not have access to before you display a secure section you simply check to see if the section id is in the session.AccessSections.

If you need more help then this let us know.

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

MFredinAuthor Commented:
Thanks guys, this gives me a good idea on how to put this together.  So I understand the concept, but could you give me a quick example of how I can give each page and each section within the page a unique ID and how I will compare it to my PageAccess and SectionAccess session variables?

@MFredlin,  you have three good options above.  You need to choose the best fit for your application.  The three options are in order of ease/power of use.  Duncan's suggestion is the easiest to implement where you simply choose a role/user type for each user and then check test for it on each page.  The second, mine, instead of checking the role on each page, you would check a "feature" which is associated with a role.   That makes a "feature" page-specific.  Nathan suggests that you use the database to identify the abilities per page/section.  Thus each page has it's own ID and you can control it's access at the database.

IMHO, my suggestion is a good compromise between the two.  It gives you some power and not too much administration.

I find that that you can "group" the needs of your system by what I am calling a "feature."    Rather than having to set up a database with every page and all the types of users for that page, you can group your page capabilities into features.  For example, you can create a feature to "Maintain Users."   On your pages to list users, edit users, delete users, update users, etc.  You simply test for the feature "Maintain Users."    In your admin, you can assign this simple feature to one or more roles (user types).    To me, this is much easier than having to maintain all 4 or 5 pages seperately in your datatbase.  

Here's how you do it.   While you code, think of the capability you are working on, such as "Managing Products"     Add a "feature" to the database for this capability and then test for it on each page associated with that capability.

<cfquery name="getFeatures" .... >
 select featureCode
  from users U
   inner join RoleFeatures T on T.feature_id = F.feature_id
                    and T.Role_id  = U.role_id

<cfset request.myFeatures = valueList(getFeatures.featureCode)>

Now, in your code you simply test the user's list of features, against the feature needed for your page.

<cfif listFindNoCase(request.myFeatures,"MaintainUsers") eq 0>
    Sorry, you don't have access to do this.

MFredinAuthor Commented:
@gdemaria.  Thanks. I think I got it.  Grouping things into features is a good idea.  

I'll give it a shot and come back with any questions. Thanks!
MFredinAuthor Commented:
Thanks for the help guys.  The permission system works awesome!

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now