 | 
June 11th, 2008, 10:46 AM
| | Member | | Join Date: Jan 2008
Posts: 85
| | Problem Creating a User Object
Hi,
I've been trying to implement a more OOP oriented approach to dealing with user security on one of my websites, and I am trying to validate the user against an array of roles, however I am struggling with a type error: -
The argument ROLES passed to function setRoles() is not of type array.
-
If the component name is specified as a type of this argument, the reason for this error might be that a definition file for such component cannot be found or is not accessible.
-
-
The error occurred in D:\***\***\AppTest\com\user.cfc: line 50
-
-
48 : <cffunction name="getRoles" access="public" output="true" returntype="array">
-
49 : <cfreturn variables.roles />
-
50 : </cffunction>
-
51 :
-
52 : <cffunction name="setRoles" access="public" output="false" returntype="void">
-
I am definately passing in an array, or at least a list which I think are basically the same thing? Here is my code for the instantiating the User object (contained in /index.cfm): -
if(NOT isDefined("Session.user")) {
-
Request.Ses.user = createObject("component","com.user").init(Request.App.Dsn);
-
Request.Ses.user.setUsername("eddy");
-
Request.Ses.user.setPassword("eddy");
-
Request.Ses.user.setRoles("staff, user");
-
}
-
and here is the User.cfc object:
Could someone point out where I am going wrong?
Thanks,
Chromis
| 
June 11th, 2008, 10:56 AM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
You're passing a list rather than an array. What you could do is accept a string as the input and convert to an array in the function, or create the array with cfset and pass that to setRoles.
| 
June 11th, 2008, 11:27 AM
| | Member | | Join Date: Jan 2008
Posts: 85
| | Quote: |
Originally Posted by acoder You're passing a list rather than an array. What you could do is accept a string as the input and convert to an array in the function, or create the array with cfset and pass that to setRoles. | Ah right ok I'll do that. Thanks alot for your help, I'll no doubt have some questions shortly!
| 
June 11th, 2008, 11:39 AM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
No problem, if you do, you know where to come :)
| 
June 11th, 2008, 02:41 PM
| | Member | | Join Date: Jan 2008
Posts: 85
| | Quote: |
Originally Posted by acoder No problem, if you do, you know where to come :) | Ok I'm getting a little confused, basically I want to create an OOP method for validating a user, the user must have a valid username, password and also have one of the roles for the particular page that they are viewing.
I've got the fundamentals of the validation working now, though i'm sure i'm not getting the structure of the User.cfc quite right. I've read about OOP and it talks about DAOs and Gateways I have tryed to implement this sort of structure. Tho I have struggled to separate the database calls into a Gateway file.
At the moment i seem to have a kind of mis-match of the two in one file. Could you tell me how i could improve this code?
Instantiation and data output (/index.cfm): -
<cfscript>
-
if(NOT isDefined("Session.user")) {
-
Request.Ses.user = createObject("component","com.user").init(Request.App.Dsn);
-
Request.Ses.user.setUsername("eddy");
-
Request.Ses.user.setPassword("eddy");
-
}
-
</cfscript>
-
-
<cfdump var="#Request#">
-
-
<cfoutput>Validate result: #Request.Ses.user.validate()#</cfoutput>
-
Roles: <cfoutput>#Request.Ses.user.getRoles()#</cfoutput>
-
Actual Roles:<cfoutput>#Request.Ses.user.getActualRoles()#</cfoutput>
-
Validate roles: <cfoutput>#Request.Ses.user.checkRoles("staff,user")#</cfoutput>
-
User DAO / Gateway (/com/User.cfc):
The parts I want to look at specifically are the checkRoles and validate methods. Should I put them into one method or attempt to separate the checkRoles and validate database calls into two different methods and have one validate method? I'm a bit confused :)
Thanks,
Chromis
[code]
| 
June 11th, 2008, 03:15 PM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
It probably would be a good idea to put the database calls in its own object which you can instantiate/call when the user object is initialised. Then it'd smply be a function call to make the query which would return true/false or a result struct. As for the validate() and checkRoles() functions, it depends on whether you ever need only the checkRoles function. If you do, you can call checkRoles within validate should validate() also validate roles.
| 
June 12th, 2008, 12:52 PM
| | Member | | Join Date: Jan 2008
Posts: 85
| | Quote: |
Originally Posted by acoder It probably would be a good idea to put the database calls in its own object which you can instantiate/call when the user object is initialised. Then it'd smply be a function call to make the query which would return true/false or a result struct. As for the validate() and checkRoles() functions, it depends on whether you ever need only the checkRoles function. If you do, you can call checkRoles within validate should validate() also validate roles. | Thanks acoder, I'll have a go and post back what i come up with.
| 
August 5th, 2008, 11:33 AM
| | Member | | Join Date: Jan 2008
Posts: 85
| |
Hi acoder,
Ok, I'm had some time to look at this code again and I think what I need to do is create a UserDAO.cfc for my persistent data functions and then pass the user.cfc object to the UserDAO.cfc object upon initialisation, I can then authenticate and check the roles using UserDAO, is this right?
On various pages I'll need to the check the user roles against the role for that page and then redirect the user to another page, do I need to create another object for this, security.cfc for instance? My thinking is that the user objects shouldn't really be used for this sort of thing, as it's not a user objects responsibility to perform the business logic.
Thanks,
Chromis
| 
August 5th, 2008, 12:08 PM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
That's right, though you could have a method in user.cfc which performs this logic, i.e. checks that the user has the role for that page; if not, redirect.
| 
August 5th, 2008, 03:08 PM
| | Member | | Join Date: Jan 2008
Posts: 85
| |
Ok, I started going down the route of creating a separate object (security.cfc) to deal with the business logic of redirecting the user, but that got me into the realm of keeping that object persistent aswell which seemed really overkill. In the end I took your advice and put a protect function in the user.cfc to redirect the user to a different page if the roles for the user were not found. This is definately the easiest method and for this project not one that's going to cause any problems so I guess I'll stick with it.
I guess what I'm trying to find out whilst learning OOP is when to separate logic and when not to, alot of what I have read so far talks about making one object do one thing well and what felt wrong about the user.cfc having a protect function and also the database interaction functions, was that it was no longer just defining a user, but providing functions to deal with it within the application.
Could you give me any advice regarding this?
Anyway here's my protect statement which I'm putting in my index.cfm's, if the user does not have the specified role record in the database, the user will be redirected to the specified URL.
index.cfm -
Request.Ses.User.protect("staff","../index.cfm");
-
User.cfc - protect function. -
<cffunction name="protect" access="public" output="true" returntype="boolean" hint="Checks user roles against a supplied array or list">
-
<cfargument name="roles" type="string" required="true" />
-
<cfargument name="redirectURL" type="string" required="true" />
-
-
<cfif variables.checkRoles(arguments.roles) EQ true>
-
<cflocation url="#arguments.redirectURL#">
-
<cfreturn true>
-
<cfelse>
-
<cflocation url="#arguments.redirectURL#">
-
<cfreturn false>
-
</cfif>
-
-
</cffunction>
-
Again thanks for your help!
| 
August 5th, 2008, 05:51 PM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
I see what you mean. Coldfusion doesn't place any restrictions in terms of OOP, though this may change in future versions.
You could look at frameworks such as Fusebox/Mach-II which might help. You could also look into the MVC (Model-View-Controller) pattern for separation.
| 
August 6th, 2008, 11:03 AM
| | Member | | Join Date: Jan 2008
Posts: 85
| |
Ok well that's put me at ease a bit. I have looked into machII and the MVC pattern, I've only developed a couple of tests so far. I have a few questions regarding this though:
1. At what scale of application does the machII begin to be useful?
2. Is it good for rapid application development?
3. Does it lend itself well to OOP techniques?
4. What do you develop with?
| 
August 6th, 2008, 12:06 PM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
Mach-II is probably better suited for large, complex applications. Another alternative is Model-Glue which can be simpler. Both enforce MVC whereas Fusebox doesn't. You may find this article/slideshow useful which compares the three.
What do I use? I don't use any, though I probably should. If I was developing from the ground up, I would and I'd change my programming style too.
| 
August 7th, 2008, 09:41 AM
| | Member | | Join Date: Jan 2008
Posts: 85
| |
Thanks I'll take a look at that. I guess for the app i'm developing at the moment I won't be needing a framework. But from what I have seen so far I think MachII would be my choice.
Again thanks for you help i'll no doubt be asking more questions soon!
| 
August 7th, 2008, 10:21 AM
|  | Site Moderator | | Join Date: Nov 2006 Location: UK
Posts: 12,766
| |
No problem. This is an interesting discussion probably not covered in this forum before. Fire away when the need comes and I'll see what I can do :)
|  |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | | | | What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over network members.
|