Question
Optimization and Best Practices: User Goup Permissions
Hello All,
Recently I have done some soul searching on the best way to allow for complex user permissions on a web site while keeping server resources in mind. I am hoping that some of you will have some ideas or suggestions on the best way to implement a system like this using CF. First a little background:
In my CF application I assign user accounts to a permission group so different users can access different pages. For example, I can assign user 'Joe Bob' to the 'Administrators' group which can access pretty much everything, whereas the user 'Jane Smith' has been assigned to the 'Contributors' group and can only access certain pages.
Initially I assigned the permissions based on the name of the permissions group, so when the user logged on I created a session variable called AccountType which would contain the value, "Administrator", "Contributor", etc. That way, my templates could run a simple cfif to check if the person could see a particular resource,link,etc.
However, now I am expanding the permissions scheme to allow site administrators to create their own user groups with their own unique names and permissions settings. The user account types are stored in a database and each separate permission is stored as a yes/no variable in a column. For example:
UserTypeID......Name ..............CanLogIn........CanAccessProducts......CanAccessBlog.......etc...
-----------------------------------------------------------------------------------------------------------------------------------------
1 ...................Administrator.....yes................yes...............................yes
2 ...................Contributor .........yes...............no................................yes
3....................Store Manager.....yes...............yes..............................no
So the problem arises: How should these permission settings be applied for the logged in users? I want to be conscious of both server memory as well processing/requests to the DB and ease of coding. Here are some ideas that I had:
IDEA 1: When the user logs on, do just as I was doing and assign a session variable named UserType that stores the UserTypeID. Then, within application.cfm, check if the user is logged on, if yes, query the database (cached query) and get the permission values for that account type and store them in a structure which can be referenced as needed in that request.
Pros: In this method, the work appears to mostly be done by the processor, db server. Since queries can be cached, I can use the same cached query for multiple users that log into the site so more than one user can share the cached query.
Cons: I think that reading a cached query and then building a structure containing the values of the table on ever page load might be overkill and might demand unneeded processing.
IDEA 2. This method is similar to #1 in that a session variable named UserType will be created when the user logs on. However the main difference is that the database won't be queried for a permission column until it is actually needed. So if the user tries to access page xyz.cfm, coldfusion checks the appropriate column in the table based on the UserType variable and either allows the user to see it or not.
Pros: This could potentially save some server memory if there are a lot of users logged on at once and a lot of permission columns in the database.
Cons: This could be a coding nightmare and will add a lot more lines of code on many templates since pretty much every template will make at least one permissions check.
IDEA 3: Another method which might work would be when a user logs on, query the appropriate permissions records and store all of the yes/no columns as a structure in the session scope. On each page load (application.cfm), copy the structure stored in the session scope which contains all of the permissions to the local variable scope so it can be easily accessed by the page.
Pros: Using this method, I only have to query the permissions once, and then access all the variables I need because they will be stored in memory.
Cons: In the event that there are a LOT of permission variables (assuming 100 or so) this could cause each logged in user session to hold a lot of variables. I'm not sure how much server memory a structure containing 100 values is, but I want to keep that in mind so I don't hog too many resources unnecessarily.
What are your thoughts on this topic? Do you have any suggestions or ideas for handling this type of situation?
Recently I have done some soul searching on the best way to allow for complex user permissions on a web site while keeping server resources in mind. I am hoping that some of you will have some ideas or suggestions on the best way to implement a system like this using CF. First a little background:
In my CF application I assign user accounts to a permission group so different users can access different pages. For example, I can assign user 'Joe Bob' to the 'Administrators' group which can access pretty much everything, whereas the user 'Jane Smith' has been assigned to the 'Contributors' group and can only access certain pages.
Initially I assigned the permissions based on the name of the permissions group, so when the user logged on I created a session variable called AccountType which would contain the value, "Administrator", "Contributor", etc. That way, my templates could run a simple cfif to check if the person could see a particular resource,link,etc.
However, now I am expanding the permissions scheme to allow site administrators to create their own user groups with their own unique names and permissions settings. The user account types are stored in a database and each separate permission is stored as a yes/no variable in a column. For example:
UserTypeID......Name ..............CanLogIn........CanAccessProducts......CanAccessBlog.......etc...
-----------------------------------------------------------------------------------------------------------------------------------------
1 ...................Administrator.....yes................yes...............................yes
2 ...................Contributor .........yes...............no................................yes
3....................Store Manager.....yes...............yes..............................no
So the problem arises: How should these permission settings be applied for the logged in users? I want to be conscious of both server memory as well processing/requests to the DB and ease of coding. Here are some ideas that I had:
IDEA 1: When the user logs on, do just as I was doing and assign a session variable named UserType that stores the UserTypeID. Then, within application.cfm, check if the user is logged on, if yes, query the database (cached query) and get the permission values for that account type and store them in a structure which can be referenced as needed in that request.
Pros: In this method, the work appears to mostly be done by the processor, db server. Since queries can be cached, I can use the same cached query for multiple users that log into the site so more than one user can share the cached query.
Cons: I think that reading a cached query and then building a structure containing the values of the table on ever page load might be overkill and might demand unneeded processing.
IDEA 2. This method is similar to #1 in that a session variable named UserType will be created when the user logs on. However the main difference is that the database won't be queried for a permission column until it is actually needed. So if the user tries to access page xyz.cfm, coldfusion checks the appropriate column in the table based on the UserType variable and either allows the user to see it or not.
Pros: This could potentially save some server memory if there are a lot of users logged on at once and a lot of permission columns in the database.
Cons: This could be a coding nightmare and will add a lot more lines of code on many templates since pretty much every template will make at least one permissions check.
IDEA 3: Another method which might work would be when a user logs on, query the appropriate permissions records and store all of the yes/no columns as a structure in the session scope. On each page load (application.cfm), copy the structure stored in the session scope which contains all of the permissions to the local variable scope so it can be easily accessed by the page.
Pros: Using this method, I only have to query the permissions once, and then access all the variables I need because they will be stored in memory.
Cons: In the event that there are a LOT of permission variables (assuming 100 or so) this could cause each logged in user session to hold a lot of variables. I'm not sure how much server memory a structure containing 100 values is, but I want to keep that in mind so I don't hog too many resources unnecessarily.
What are your thoughts on this topic? Do you have any suggestions or ideas for handling this type of situation?
