Speaking at cfCamp

Pleased to say I’ll be speaking on CFWheels 2.x and the new CLI at CFCamp, 20-21 October 2016. Would be great to catch up with people – do come and say hello (and indeed, come to my session!)

Session Details:

CFWheels 2.x and the new CLI

CFWheels is an open source CFML framework inspired by Ruby on Rails that provides fast application development, a great organisation system for your code, and is just plain fun to use. One of our biggest goals is for you to be able to get up and running with CFWheels quickly.

We want for you to be able to learn it as rapidly as it is to write applications with it. CFWheels has a long history, with the first commit over 10 years ago. Over 3000 commits later, this talk will take a look at what’s new in CFWheels 2.x, which brings huge leaps forward with tonnes of new features integrated into the core.

Along with 2.x comes the new CLI commands for CommandBox, which allow real “rails-style” scaffolding, complete with database migrations, controller, model and view templating, ability to run test suites from the command line, and much, much more.

Even if you’re not familiar with CFWheels, this talk will aim to give you enough to get going on your first app at breakneck speed!

Using Oracle 12c in Lucee – ORA-28040: No matching authentication protocol

Disclaimer: I don’t use Oracle, ever, and this was just to get a local testing environment setup.

I’d installed Oracle 12c, and when trying to add a datasource in the Lucee admin, kept on getting “ORA-28040: No matching authentication protocol”.

According to StackOverflow there’s a bug, where’s the simple fix is to add the line:

SQLNET.ALLOWED_LOGON_VERSION=8

To

C:\app\Oracle\product\12.1.0\dbhome_1\NETWORK\ADMIN\sqlnet.ora

CFWheels CLI for Commandbox (Alpha Test)

Ok.. so this is what I’m working on at the moment. Work in progress! It’s the beginning of a port of the Rails CLI, but for CFWheels using Commandbox.

cfWheels: hasChanged() and changedFrom()

One of the more overlooked nice features of cfWheels is the ability to determine whether an object’s properties have changed before you save them. With that information, we can then easily set other model properties dependent on the change.

Why would we do this? Let’s take an example of a ticketing system where each ticket would have a status, i.e “Available, Pending Payment, Sold, Void”, but for each of those conditions, other columns in your dataset might need to be altered, and you only want to alter them when the status actually changes, not every time the object is saved.

So if a ticket’s Status goes from from Pending Payment-> Sold, we might want to change another column as part of the work flow, in this case, we might want to dictate that now that ticket is Sold, that it now needs to be printed out and delivered. In our example, we want to programmatically change deliverystatus to “Print Me” or something. Maybe we’ve got a condition setup which removes tickets from a shopping basket via cron job when a date has expired (these are just examples).

In wheels, we can add this logic once on the model, and then we never need to worry about it in our controllers again. The trick is using this.changedFrom(“ticketstatus”) and this.ticketstatus as the “before and after” values to compare against.

In our Ticket.cfc model’s init() method, we can add a function call to trigger beforeSave:

beforeSave("checkTicketConditions");

Then, in the same file, add a function to handle this:

public void function checkTicketConditions() {

  if(this.hasChanged("ticketstatus")){
    oldStatus=this.changedFrom("ticketstatus");
    newStatus=this.ticketstatus;

    // Reserving Tickets in shopping basket
    if(newStatus EQ "INBASKET"){
      this.removeFromBasketAt=dateAdd("s", 3200, now());
    }

    // Remove cron basket timelimit (i.e, when the status changes from INBASKET to anything)
    if(oldStatus EQ "INBASKET"){
      this.removeFromBasketAt="";
    }

    // etc
  }

  // Update delivery status
  if(this.hasChanged("delivery")){
    if(this.delivery EQ "eticket"){
      this.deliverystatus="PENDING EMAIL DELIVERY";
    } else if(this.delivery EQ "postal"){
      this.deliverystatus="PRINT AND POST ME";
    } else if(this.delivery EQ "pickup"){
      this.deliverystatus="PRINT ME";
    }
  }
}

With this type of model logic you can actually fire off some pretty complex workflows, and keep it all out of your controller!

cfWheels Plugin Survey

Use cfWheels? Help us get an idea of what plugins you guys use, and which you think might qualify for some core team support! The survey will only take a minute – please do fill it in if you use any plugins in cfWheels..

https://www.surveymonkey.com/s/9P7PJCV

cf10/ MAMP & OSX Yosemite

Just a reminder, installing OSX Yosemite will nuke your java install.

Re-download from here.

You’ll probably need to restart coldfusion from terminal when in /Applications/coldfusion10/cfusion/bin using

 ./coldfusion start

Also, if you’re running it through MAMP, then you’ll need to do this silly workaround if apache doesn’t start: rename “envars” to “_envars” in /Applications/MAMP/Library/bin.

Then restart everything. Worked for me!

Mura CMS vulnerability – might apply to your cfWheels app

Just a head’s up:
This recent Mura CMS issue is something which could possibly apply to a wheels app:

http://www.trunkful.com/index.cfm/2014/1/29/Mura-CMS-Vulnerability

I’m not referring to the file manager upload bit (although that could possibly apply), but the role escalation. That is, rewriting POST variables and resubmitting in order to gain admin privs.

Ask yourself, “do I have a public user account creation form” – if not, and user creation is always by an admin level user to start with (and that the user controller is sufficiently locked down), you’re probably fine.

But if you have a user creation form which is publicly accessible,  have you used cfWheels protected properties for the ‘role’ field, or something like ‘isAdmin’ field?

Have a think how but submitting a custom POST request, but simply changing role=”admin” could affect your application. I know I’ve been guilty of this in the past! One quick solution if you don’t want to go down the protected properties route is to separate out your role functions into a separate view/function, which can then do specific checks, and in the user account creation, overwrite any role value passed in with a sensible default.

There’s more on this here – https://groups.google.com/forum/?fromgroups#!searchin/cfwheels/mass$20assignment/cfwheels/bOQo9-CHJlA/xtAVjcvzNMgJ 

This isn’t an issue with wheels per se, just a very common coding practice which can potentially leave a hole open to attack!

Things learned from creating the RoomBooking System (part 2)

The Room Booking system is now available as v 1.01; the main addition being permissions, roles and authentication. As before, I thought it might be useful to highlight a few of the thought processes behind this update, and look at some of the problems come across when beginning to think about an application which is due for distribution in all sorts of environments.

Authentication varies massively depending on the setup – here are a few common scenarios:

Using authentication external to the application, i.e at a IIS/Apache level:

  1. Block the whole website: e.g, have everything behind apache’s htpasswd authentication, or restrict to a specific IP Range, or VPN connection etc
  2. Block only “admin” level functions: e.g specific authentication triggered for all /admin/ requests: again, trigger via .htpasswd or somesuch.
  3. Using Active Directory/LDAP to authenticate a user, and use groups specified outside the main application to load a user into a specific role
  4. Other SSO systems (shibboleth etc) integrated into IIS/Apache

Authentication within the application:

  1. Using traditional cflogin, and built in CF login functions
  2. Testing for session based variables specifically, i.e session.user.loggedinAt

Obviously there are a million other variations on this, but it does highlight that whatever your doing should at least consider these other methods.

What are you trying to protect?

Obviously, this is the first question you have to ask yourself. What is it that requires some level of authentication? Nine times out of ten, it’s the privilege of changing or viewing data, that much is pretty self explanatory. But it’s worth considering all data you’re storing, and how that might be used. For instance, blocking the web interface of an application is one thing, but what about potential API usage? RSS Feeds? Other connection types which don’t require a browser? For the Room Booking system (RBS after this point, I can’t be bothered with the typing), it’s relatively straightforward, at least at the moment. But in the future I’m planning to add RSS/iCS/JSON/XML feeds – perhaps only read only, but whatever authentication system, I’ve got to consider future usage.

What I ended up with:

In order for the RBS to be as flexible as possible to the most number of users, I ended up decided on (application specific) Role based permissions. In short, if person ‘bob’ is in role ‘admin’, and tries to do ‘x’ there needs to be some sort of permissions matrix indicating the admin role’s permission to do ‘x’. The important part to note here is that I’m not ever directly testing against a role. There should be  no conditional statements like if(isAdmin(user)) then do ‘x’; this leads to a nightmare later on when you suddenly decide you want to add a role, as for each ‘isAdmin()’ check, you then have to start adding ‘isEditor()’ or somesuch, and probably all over your application.

It’s better to build a privilege called ‘canDoX’ and test against that, as roles can more easily be added in the future.

Wheels lets us handle this quite neatly with two models, users & permissions. A user has a role, such as ‘admin’ or ‘editor’ etc; Then in the permissions table, you have a permission key, which is the name of your permission, i.e canDoX, and a column for each role, with a tinyint of 1 or 0 depending. So it’s a simple matrix of yes/no type data.

Then, onApplicationStart, we can check for an load in the matrix of permissions into the application scope for referencing later:

<cfset application.rbs.permissionsQuery=model("permission").findAll()>
 <cfloop query="application.rbs.permissionsQuery">
   <cfscript>
      application.rbs.permission["#id#"]={};
      application.rbs.permission["#id#"]["admin"]=application.rbs.permissionsQuery["admin"];
      application.rbs.permission["#id#"]["editor"]=application.rbs.permissionsQuery["editor"];
      application.rbs.permission["#id#"]["user"]=application.rbs.permissionsQuery["user"];
      application.rbs.permission["#id#"]["guest"]=application.rbs.permissionsQuery["guest"];
   </cfscript>
 </cfloop>

Once we’ve got these in the application scope, all we need are four functions to handle most of the permission based work:

<cffunction name="checkPermission" hint="Checks a permission against permissions loaded into application scope for the user" returntype="boolean">
	<cfargument name="permission" required="true" hint="The permission name to check against">
	<cfscript>
		if(_permissionsSetup() AND structKeyExists(application.rbs.permission, arguments.permission)){
			return application.rbs.permission[arguments.permission][_returnUserRole()];
		}
	</cfscript>
</cffunction>

<cffunction name="checkPermissionAndRedirect" hint="Checks a permission and redirects away to access denied, useful for use in filters etc">
	<cfargument name="permission" required="true" hint="The permission name to check against">
	<cfscript>
		if(!checkPermission(arguments.permission)){
			redirectTo(route="denied", error="Sorry, you have insufficient permission to access this. If you believe this to be an error, please contact an administrator.");
		}
	</cfscript>
</cffunction>

<cffunction name="_permissionsSetup" hint="Checks for the relevant permissions structs in application scope">
	<cfscript>
		if(structKeyExists(application, "rbs") AND structKeyExists(application.rbs, "permission")){
				return true;
		}
		else
		{
			return false;
		}
	</cfscript>
</cffunction>

<cffunction name="_returnUserRole" hint="Looks for user role in session, returns guest otherwise">
	<cfscript>
		if(_permissionsSetup() AND isLoggedIn() AND structKeyExists(session.currentuser, "role")){
			return session.currentuser.role;
		} else {
			return "guest";
		}
	</cfscript>
</cffunction>

So all you’d need to do using the above is:

<cfscript>
if(checkPermission("canDoX")){
// Do stuff
}
</cfscript>

The checkPermissionAndRedirect() function is very similar, and can be used on a filter level in your controller to just push away the user if they shouldn’t be accessing a view/function etc

i.e, on my Locations.cfc controller, where CRUD updating for the RBS board locations takes place:

filters(through="checkPermissionAndRedirect", permission="accessLocations");

The advantages of this approach are:

  • You’ve got an ‘out-the-box’ system which doesn’t require extensive server setup
  • You could extend this principle to allow for 3rd party authentication – i.e, if you’re going via LDAP, once a user is approved, a ‘local’ account could easily be created which duplicates core information such as email/name from the initial authentication (see an example I did a few years ago here)
  • Permissions are cached in the application scope, meaning you potentially avoid another database hit for every user login
  • In the future, user based permissions which override role based permissions could easily be added: our checkPermission(“foo”) function could easily look for the equivalent key in the user’s session scope
  • Adding new permissions to use is as simple as adding a line in the permissions table
  • Each installation can redefine the abilities of each role to suit their needs: so in the RBS example, you could make every role do everything, and then use some other authentication method, or lock down guest users etc.

All this code can be seen in context at the GitHub Repo

Things learned from creating the RoomBooking System

Since launching my little Room Booking system as an open source project, I thought it might be useful to highlight a few techniques used which others might find useful. Obviously, this isn’t to say that this is the ‘only way to do x’, but merely to flag some ways to approach common problems. All the below can be seen in context at the gitHub repo

events/functions.cfm

One issue a had a while back was determining the IP address of a user. Now, historically, this wasn’t an issue, as cgi.remote_host worked fine. However, since Railo’s installer changed the way it forwards requests from Apache (mod_jk-> mod_proxy), it always saw the remote IP as 127.0.0.1. This function checks the incoming request header and tries to grab the IP there, rather than in the CGI scope.

<cffunction name="getIPAddress" hint="Gets IP address even from Railo" returntype="String">
<cfscript>
   var result="127.0.0.1";
   var myHeaders = GetHttpRequestData();
    if(structKeyExists(myHeaders, "headers") AND structKeyExists(myHeaders.headers, "x-forwarded-for")){
      result=myHeaders.headers["x-forwarded-for"];
    }
    return result;
</cfscript>
</cffunction>

events/onrequeststart.cfm

This simply checks every incoming request for the URL or FORM scope, loops over each key in the struct, and trims the whitespace.

<cfif StructCount(form)>
	<cfloop collection="#form#" item="key">
		<cfset form[key] = Trim(form[key])>
	</cfloop>
</cfif>
<cfif StructCount(url)>
	<cfloop collection="#url#" item="key">
		<cfset url[key] = Trim(url[key])>
	</cfloop>
</cfif>

Personally, I think cfWheels should do this by default, but then, it would probably break a load of people’s applications. Simply put, I can’t imagine a case where I’d want whitespace at the beginning or end of any key in my url or form scope.

view/helpers.cfm

This one was an interesting one – Javascript often passes it’s values in Epoch time, i.e number of seconds since 1970; I needed to convert this to localTime in a few places. Surprisingly, I’ve never had to do this before!

<cffunction name="eToLocal" hint="convert epoc to localtime">
	<cfargument name="e">
	<cfreturn DateAdd("s", arguments.e ,DateConvert("utc2Local", "January 1 1970 00:00"))>
</cffunction>

So Bootstrap3 has panels. I love panels. But I’m lazy, I don’t want to type out the markup for a panel all the time. So these two helpers do it for me:

<cffunction name="panel" hint="Renders a bootstrap Panel">
    <cfargument name="title" required="true">
    <cfargument name="class" default="panel-default">
    <cfargument name="ignorebody" default="false">
    <cfset var r ="">
    <cfsavecontent variable="r"><Cfoutput>
    <!--- Start Panel --->
    <div class="panel #arguments.class#">
        <div class="panel-heading">
            <h3 class="panel-title">#arguments.title#</h3>
        </div>
        <cfif !arguments.ignorebody>
        <div class="panel-body">
        </cfif>
    </Cfoutput>
    </cfsavecontent>
    <cfreturn r />
</cffunction>

<cffunction name="panelend" hint="Close Panel">
    <cfargument name="ignorebody" default="false">
    <cfif !arguments.ignorebody>
        <cfreturn "</div></div>" />
    <cfelse>
        <cfreturn "</div>" />
    </cfif>
</cffunction>

Usage:

#panel(title="foo")#
.. things here
#panelEnd()#

Sometimes Bootstrap needs it’s content to be flush with the panel, so you occasionally need to ignore the panel-body – flush list-group-items – I’m looking at YOU.

#panel(title="foo", ignorebody=true)#
<ul class="list-group">
<li class="list-group-item">FOO</li>
</ul>
#panelEnd(ignorebody=true)#

Previously, I’d have done this using custom tags, i.e , but with the added import needed on every page, I find this a *lot* quicker/easier.

views/layout.cfm

One of things I like to do is have all the CSS in the header, and all the JS in the footer. So what happens when you want to do your JS stuff in your view folders? Here’s one solution..

In your view file, simply wrap your JS bits in cfsavecontent, i.e

<cfsavecontent variable="request.js.mystuff">
<script>// JS goes here</script>
</cfsavecontent>

Then in your layout file, after all your calls to jQuery etc:

<cfif structkeyexists(request, "js")>
<cfloop list="#structKeyList(request.js)#" index="key"><cfoutput>#request.js[key]#</cfoutput></cfloop>
</cfif>

The only thing this doesn’t really deal with is calling JS in a specific order, as structs are by their nature, unordered. I guess you could turn this principle into an array based system easily enough though: generally speaking, I haven’t found needing to write JS over many view files which needs to be executed in a specific order. YMMV.

bookings/index.cfm

This bit of JS is very useful:

 $('body').on('hidden.bs.modal', '.modal', function () {
        $(this).removeData('bs.modal');
});

Bootstrap caches modals which have had dynamic data inserted in, so initially, when I was building it, every time I clicked on an event, the modal would display the first event I’d click on’s data. This destroys the modal data after you close it. Handy.

And another thing…

The last thing to note is that this has an example of using Ajax in cfWheels, examples of which are fairly rare. If you’re interested in how that’s done, look at the javascript call in bookings/index.cfm under event sources: it’s just a jQuery ajax request. Now look at controllers/Eventdata.cfc = you’ll see the renderWith call, and if you look at the function ‘prepdata’, you’ll see me converting a query into a array of data (in the format I wanted it), which is then passed back by wheels using renderWith(events);

So there you go. If, of course, you guys have better ways of handling the above, I’d love to hear them.