Fusebox NOXML permissions
One of things I miss about the XML approach is the permissions attribute for circuit and fuseaction. My solution is to use MetaData, so you could do something like:
<cfcomponent extends="com.ControllerCircuit"
output="false"
hint="I am the foobar circuit">
<cffunction name="home"
access="public"
output="false"
permissions="Developer,Designer">
<cfargument name="myFusebox" />
<cfargument name="event" />
... do something ...
</cffunction>
<cffunction name="prefuseaction"
access="public"
output="true"
hint="I process pre fuseaction execution">
<cfargument name="myFusebox" />
<cfargument name="event" />
<cfset arguments.event.xfa( "login", "foobar.login" ) />
<cfset super.prefuseaction( myFusebox, event ) />
</cffunction>
</cfcomponent>
Note the permissions attribute I've added to the home fuseaction. Each "circuit cfc" extends ControllerCircuit.cfc and calls it's prefuseaction method.
ControllerCircuit.cfc
<cfcomponent output="false"
hint="I am the Controller Circuit superclass">
<cffunction name="prefuseaction"
access="public"
output="true"
hint="I process pre fuseaction execution">
<cfargument name="myFusebox" />
<cfargument name="event" />
<cfset var index = 0 />
<cfset var authorised = False />
<cfset var fuseMetaData = getMetaData( this ).functions />
<cfset var User = Application.BeanFactory.getBean( "MemberService" ).getCurrentUser() />
<cfloop from="1" to="#ArrayLen( fuseMetaData )#" index="index">
<!--- myFusebox.getCurrentFuseaction() not available in production mode so using myFusebox.ThisFuseaction --->
<cfif Compare( fuseMetaData[ index ].name, arguments.myFusebox.ThisFuseaction ) EQ 0>
<cfif StructKeyExists( fuseMetaData[ index ], "permissions" )>
<cfset allowedroles = fuseMetaData[ index ].permissions />
</cfif>
<cfbreak />
</cfif>
</cfloop>
<cfset authorised = User.HasAnyRole( allowedroles ) />
<cfif NOT authorised>
<cfset arguments.myFusebox.relocate( xfa="login" ) />
</cfif>
</cffunction>
</cfcomponent>
The above code doesn't make use of ColdFusion's inbuilt security methods. Personally I think cflogin it is more trouble than it's worth, and I'd much rather have a User object, but if you really want to you can use cflogin with a few minor alterations you can:
<cfcomponent extends="com.ControllerCircuit"
output="false"
hint="I am the foobar circuit">
<cffunction name="home"
access="public"
output="false"
roles="Developer,Designer">
<cfargument name="myFusebox" />
<cfargument name="event" />
... do something ...
</cffunction>
<cffunction name="prefuseaction"
access="public"
output="true"
hint="I process pre fuseaction execution">
<cfargument name="myFusebox" />
<cfargument name="event" />
<cfset arguments.event.xfa( "login", "foobar.login" ) />
<cfset super.prefuseaction( myFusebox, event ) />
</cffunction>
</cfcomponent>
Note the roles attribute (which works in partnership with cflogin) I've added to the home fuseaction in place of my custom permissions attribute. As before, each "circuit cfc" extends ControllerCircuit.cfc and calls it's prefuseaction method.
ControllerCircuit.cfc
<cfcomponent output="false"
hint="I am the Controller Circuit superclass">
<cffunction name="prefuseaction"
access="public"
output="true"
hint="I process pre fuseaction execution">
<cfargument name="myFusebox" />
<cfargument name="event" />
<cfset var index = 0 />
<cfset var authorised = False />
<cfset var fuseMetaData = getMetaData( this ).functions />
<cfloop from="1" to="#ArrayLen( fuseMetaData )#" index="index">
<!--- myFusebox.getCurrentFuseaction() not available in production mode so using myFusebox.ThisFuseaction --->
<cfif Compare( fuseMetaData[ index ].name, arguments.myFusebox.ThisFuseaction ) EQ 0>
<cfif StructKeyExists( fuseMetaData[ index ], "roles" )>
<cfset allowedroles = fuseMetaData[ index ].roles />
</cfif>
<cfbreak />
</cfif>
</cfloop>
<cfset authorised = IsUserInAnyRole( allowedroles ) />
<cfif NOT authorised>
<cfset arguments.myFusebox.relocate( xfa="login" ) />
</cfif>
</cffunction>
</cfcomponent>
I haven't tried this on a high traffic website but it seems to work well. My thoughts are to store the MetaData in the application scope as each circuit is called to improve performance. Fusebox XML stored this in myFusebox.getApplication().circuits[ mycircuitname ].permissions. In the no XML variation this structure this exists, it just has blank values.
It is worth pointing out that you can't use the roles attribute without cflogin - if you do then you'll get the exception "The current user is not authorized to invoke this method."
Feedback welcome as always!
- Posted in:
- ColdFusion
- Fusebox


Seems like it would suit your needs, unless I'm mistaken?
Cheers,
Jeff D.
Comment by Jeff D. – February 08, 2009
There is a bit more discussion on my approach at which you may be interested to read in Fusebox Yahoo Groups thread on this: tech.groups.yahoo.com/group/fusebox5/message/4109
Comment by John Whish – February 08, 2009
Thanks for you feedback :)
Comment by John Whish – February 09, 2009