SerializeJSON() and ORM watch out!

I'm not sure if this is a bug or the way ColdFusion 9.0.1 works, but today I had an issue with the way ColdFusion was serialising an ORM Entity.

I was making a simply AJAX call and in CF using serialiseJSON() method on an ORM object. My issue was that any object that had a property that was an array of other objects was not being returned.

I posted the issue on stackoverflow but then I remembered having the same issue in a Google Group Post on Taffy. I remember resolving this at the time by splitting up the object and basically recreating it again. I was about to do the same thing then on the Adobe livedocs and spotted "remotingFetch"

Quote: "If remotingFetch is false, then the value of that attribute is not sent over flash remoting. The attribute is true by default for all properties. However, for ORM CFCs where persistent = true, the value of the remotingFetch attribute is set to false, by default, for one-to-one, one-to-many, many-to-one, or many-to-many relationships. After enabling this on my relationship it fixed the issue! However as this was referred to under "flash remoting." I missed it the first time around."

After enabling this on my relationship it fixed the issue! As this was referred to under "flash remoting." I missed it the first time around. Just something to watch out for.

Sep27

API Authentication with Taffy

Recently I have been working with Taffy to create a simply REST API. The API is used by a native mobile application on the iPhone. When it was complete I needed a simply way to authentication the application talking to the API.

This is not something I was familiar with at all. I looked into lots of different methods before I started. I really did not want, nor have the experience to reinvent the wheel, so I look at current methodologies around the web.

My first attempt was BASIC authentication, but this did not feel right. For reasons I won't go into here, the API was not over HTTPS, anyone could sniff out the password. Bad, very bad!

I found a really good post by Greg Moser on AJAX Authentication with Taffy REST API. He talks about using sessions as an API key. This is a good idea, but as my application is mobile, not really applicable for my situation. However his post did get me thinking and was very helpful.

I didn't need the complexity of OAuth. I found that I liked the way Amazon secures their API. So I looked more into this approach.

I needed a simple "half OAuth" approach. Mainly without the user having to approve. This is how I got my head around it all and what I ended up with, code and explanation below.

Continue Reading

Sep22

Check file size before ColdFusion upload

I found a neat little way of checking a file size before full upload in CF by using Java io. In Java the following "file.length();" will get the number of bytes in the file. In CF you can do this...

view plain print about
1createObject("java","java.io.File").init("image.png").length()

So something like this is neat and tidy.

view plain print about
1if (createObject("java","java.io.File").init("image.png").length() gt xx)
2 return false;
3 else
4 fileUpload("D:\","#arguments.image#","","makeUnique");

There are of course many other ways of doing this, but simple things like this impress me.

Sep19

CFMAP: address not valid error message solved

After some minor frustration today with CFMAP and the way it sends addresses to a geocoding service, I am now back on track. I just wanted to write a quick post for anyone else that may run into the same issue. CFMAP was leading me down the wrong path, telling me a bunch of addresses were invalid - "not found". When I directly used the geocoding functionality from Google to test the addresses i.e.

view plain print about
1"http://maps.google.com/maps/geo?q=#address#&output=csv&sensor=false&ke y#yourgooglekey#
2200,5,52.6006027,-1.1840779

Google returned "ok" status code, including the longitude and latitude details I needed. The addresses was indeed valid as far as Google was concerned. So something else was afoot.

Next, I tried the longitude and latitude values in CFMAP and excluded address attribute. This time however all my 50 markers were loaded correctly with no errors.

I looked at the Google Maps API in more detail. I found they had implemented a geolocation service that takes the address you've supplied, and then converts it to longitude etc. As it turns out this geolocation service restricts the total number of requests, per second you can make. It seems CFMAP uses this same geolocation service when you don't have longitude or latitude in your map item tag.

Looking at my own source, ColdFusion makes all the requests to this service in just one call. After the confusing error message, I was beginning to think this was my issue and not that the addresses were invalid.

Anyhow, a quick Google, and Jedi Master to the rescue! Easy when you know what to search for, right?

Ray resolved this issue by calling a CFC to get the lat and lon points, then sleeping for 500ms before continuing in the loop, he saves the results into the application scope and then keep looping, checking if it exists until he has them all in this app scope.

I decided to use this solution, but in a different way. I did not want to use the application scope because my data changes to often.

So I change my approach. I created two new fields in my database for both longitude and latitude. When my users creates a new "address" via my backend, I create the Google Geocoder V3 CFC. And then save the results to a database. As my users add events one at a time, I would not run into the restriction here... Well, I could, but it's very unlikely, right?

view plain print about
1// Geo Get Funtions
2local.geo = createObject("component", "eventManagerApp.com.utility.googlegeocoder3");
3local.geoResults = geo.googlegeocoder3(address="#rc.venueDetails.getvenueAddressLine1()# & #rc.venueDetails.getvenuePostCode()#");
4// Save Geo Function
5rc.venueDetails.setvenueLon(local.geoResults.longitude);
6rc.venueDetails.setvenueLat(local.geoResults.latitude);
7rc.venueDetails.setvenueAddressType(local.geoResults.result_type);
8// Save
9rc.venueDetails = geteventVenueService().save(entity=rc.venueDetails);

I could now use the raw longitude and latitude data without calling the geo service by using the address attribute and incurring the per second restrictions.

I loaded over 50 markers without any issues! Thank You... O, and what a run around!

Apr14

Mura FW/1 and ValidateThis Plugin

I had a few hours today which I set aside to learn more about FW/1 and ValidateThis. I wanted to use both of these frameworks within a Mura Plug-in I had created. I have never used ValidateThis, so I wondered how hard it would be to add it into the fw/1 Plug-in. I am not saying below is the best way, it's my first attempt and I welcome ideas :)

Continue Reading

Jan31

Mura CMS URL rewriting for Windows IIS7

It has been sometime since my post on friendly URL's in Mura CMS. A lot has changed, it's now even easier to have friendly URL's. Best of all it only takes a few seconds.

Getting rid of the siteID & index.cfm

First open the config/settings.ini.cfm file. We are interested in two settings, siteidinurls and indexfileinurls. Change both of these to 0.

view plain print about
1siteidinurls=0
2indexfileinurls=0

Note: If you get rid of siteid and plan to run more than one site on the same instance of Mura, then all you have to do is change your bindings in IIS 7 to match what you have setup for each site in Mura. Doing this means you can have each site on their own domain running from one instance of Mura, cool or what?

Now, logon to your Windows Server 2008 and install the rewriting extension found here. Install either the 32bit or 64bit depending on your OS.

Once installed, open up your Mura site in the IIS 7 Manager. Then double click on the new URL "rewrite" icon. You will now see on the right hand side under actions, an option called "Select Import Rules". Click this and enter the following in the rewrite rules box and click apply...

view plain print about
1RewriteEngine On
2RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-d
3RewriteRule ^([a-zA-Z0-9/-]+)$ /index.cfm%{REQUEST_URI} [PT]

Lastly restart the website and then Mura. Thats it.

Jan23

You Can Shape Slatwall: Full Ecommerce Plug-in for Mura

FusionSell has had a good response and I have had lots of positive emails. One of the emails I received was from Greg Moser. Greg  has already spent a lot of time creating a ecommerce Plug-in for nytro.com, and is now currently developing a full ecommerce plug-in for Mura called Slatwall. Both Greg and I listened  to the same cfhour podcast and the words of Sean Corfield resonated around both our heads.

Greg seems very passionate about open source and ColdFusion, we both came to the conclusion not to double work load. Why end up with two OK products when Slatwall could be a single great product.

Continue Reading

Dec18

ColdFusion Shopping Cart Plug-in, Project Help needed!

This post is in response to alot of emails I am getting regarding FusionSell. I cannot believe just how much need there is for an ecommerce plug-in for Mura. However, I cannot do this alone!

A total of 4 hours and no planning does not always lend it's self to a long stainable project. However, sometimes, something very small can be the start of something beautiful.

FusionSell is by no means beautiful, but after being inspired by episode 81 of CFHour I can see FusionSell becoming much more with the help of others.

In .NET I have lots of options, in ColdFusion not so many. But nothing in CF seems to combine a good CMS with a ecommerce store. Mura CMS has given us the perfect platform to create this package. It's easy, open and most importantly extendable.

FusionSell is my attempt at a plug-in I am hoping can be turned into something more, but I need your help!

My mission is to create an open source shopping cart plug-in for Mura CMS that's easy to use, follows best practice and most importantly free. Free to anyone, for any propose.

Continue Reading

Dec11

Mura: Simple Shopping Cart Plugin

I wanted to produce a very simple shopping cart (no payment gateways) for a client of ours. There are a few shopping cart plug-ins coming after Christmas like Meld ecommerce and Slatwell. However, I just wanted some thing now that's simple and fast to share with anyone who's intrested. So I produced FusionSell for Mura. It does however need a lot more work, but it's a testimony to how quickly and easily you can write a plug-in for Mura - if I can do it anyone can!

If people find this plugin useful, I will actually turn it into something more, 'ecommerce like' with payment gateways using the FW/1 framework.

Anyway, take a look at the setup video I did below if you have time. It feels like it took me longer to learn Camtasia then it did to do this plug-in. You can find the actual plug-in at RIAForge when I remeber my password! Temp files can be found at the URL below for the time being.

I only tested this plugin on CF8.

Update: on RIAForge :here

Nov26

Setting up Security Roles in ColdBox

Fake Jake is back. He wants to secure some of his events based on 'roles' within ColdBox. ColdBox has security baked in with it's core security interceptor, so this should be easy....

ColdBox 3 (I am using M6 version) gives us a .cfc based config file, and this is where I will be declare the security interceptor.

view plain print about
1//Interceptors
2interceptors = [
3 //security
4 {class="coldbox.system.interceptors.security",
5 properties={rulesSource="xml",
6 rulesFile="/config/securityRules.xml.cfm",
7 debugMode="false",
8 preEventSecurity="true"}}    
9    ];

From the above you can see I have told the interceptor where to find my security rules. In this example I have placed my security rules in an xml file called 'securityRules.xml.cfm'. But these rules could also be pulled from a database, model and ORM etc.

Now lets have a look at the rules in this file...

view plain print about
1<?xml version="1.0" encoding="ISO-8859-1"?>
2<!--Security rule
3ex: All events in the user handler
4 user\..*
5ex: All events
6 .*
7ex: All events that start with admin
8 ^admin
9If you are not using regular expression,
10just write the text
11that can be found in an event.-->

12
13<rules>
14 <rule>
15 <whitelist>
16 general\..*,
17    login\..*
18 </whitelist>
19 <securelist>
20 dashboard\..*
21 </securelist>
22 <roles>user,admin</roles>
23 <permissions>read,write</permissions>
24 <redirect>login.index</redirect>
25 </rule>
26</rules>

As you can see we have a 'whitelist' of events that will not be verified by the security interceptor. We also have a 'securelist'. In my example this means that any event starting 'dashboard' will be secured and redirected to 'redirect' rule, in this case it's the event login.index.

Roles in my case mean that only users with the role assigned of 'user' or 'admin' will be allowed to visit the secure list of events.

That's it! We have setup our role based security in ColdBox. Now lets look at a simple login event. This event fires after the user has clicked login and it's where I will be validating their login credentials.

view plain print about
1/* validate login credentials */    
2function validateCredentials(any){
3    var rc = event.getCollection();
4    var userBean = "";
5    userBean = userService.new();//new object
6    populateModel(userBean);//populate object from scope
7    userCount = userService.countWhere(entityName="user",
8 user_name="#userBean.getuser_name()#",
9    user_password="#userBean.getuser_password()#");
10        
11    if (userCount eq 1){//correct login
12    userBean = userService.findUser();
13    userService.save(userBean);//update user login details
14    loginUser(username=userBean.getuser_name(),
15 password=userBean.getuser_password(),
16 role=userBean.getuser_role());
17    return true;            
18}
19    else {
20return false;
21}
22    }

Because I am using CFScript for my components you can see that I have to call another function called 'loginUser'. loginUser is just inside a none script based CFC that I call by extending this component. for example....

view plain print about
1<cffunction name="loginUser" returntype="void" output="false">
2<cfargument name="username" required="true">
3<cfargument name="password" required="true">
4<cfargument name="role" required="true">
5<!--- log the user in --->
6    <cflogin
7    idletimeout = "1800">

8
9     <cfloginuser
10     name = "arguments.name"
11 password = "arguments.password"
12     roles = "arguments.role">

13    </cflogin>
14
15</cffunction>

The reason for this is that CF9 does not have a script version of login.

That's really it, I have now secured my events based on user roles. For more reading visit the ColdBox Doc's

Oct06

More Entries