In the last entry, I spent a lot of time of talking about the User model behind the application. While this was important, it actually didn't have a lot to do with Model-Glue. In fact, our application didn't actually use it. Now it's time to correct that. Let's start by examining what will happen when a user logs on. First, notice the action field from our logon form:
<form action="#viewstate.getValue("myself")#logonattempt" method="post">
I talked about this in my second entry. The viewstate.getValue("myself") acts like a shorthand way of saying "root". All I needed to do was append the name of the event to run. If you tried to logon in the past few days, you would have seen Model-Glue throw an error stating that the event didn't exist. So let's add this to our ModelGlue.xml file.
<event-handler name="LogonAttempt"> <broadcasts> <message name="authenticate" /> </broadcasts> <results> <result name="loggedIn" do="Home" /> <result name="notLoggedIn" do="Logon" /> </results> </event-handler>
So what am I doing here? First I broadcast an authenticate method. This call will either return loggedIn or notLoggedIn as an event result. Notice then I check for those event results and fire the Home event or rerun the Logon event. Make sense? Now I need to add a listener for the event. In the same config file, go up to myController and add this new listener:
<message-listener message="authenticate" function="authenticate" />
Alright, we are halfway there. Now we need to add the method to the controller. Here is the code I used:
<cffunction name="authenticate" access="public" returnType="void" output="false"> <cfargument name="event" type="ModelGlue.Core.Event" required="true"> <cfset var username = arguments.event.getValue("username")> <cfset var password = arguments.event.getValue("password")>
<cfif variables.userGateway.authenticate(username,password)> <cfset session.loggedIn = true> <cfset session.userBean = variables.userDAO.read(username)> <cfset arguments.event.addResult("loggedin")> <cfelse> <cfset arguments.event.setValue("badlogin", 1)> <cfset arguments.event.addResult("notloggedin")> </cfif>
The first thing you want to notice is how I get the username and password. Notice I didn't address the form scope. Instead, since Model-Glue merges all input data for me into the event object, I simply use the event.getValue() function. The cool thing about this function is that it works just fine even if the data doesn't exist. It also works if my form switches from POST to GET method. Basically, it just works. I next talk to the gateway CFC I created in the last entry. If the authentication passes, I set a marker in the session variable (the same one I checked in the getAuthenticated method). I also use the DAO CFC to create an instance of the User bean and store that in my session. This will give me access to all the user's values. Where did I get the userGateway and userDAO from? I modified the init() method to load them on startup:
<cffunction name="Init" access="Public" returnType="Controller" output="false" hint="I build a new SampleController"> <cfargument name="ModelGlue" required="true" type="ModelGlue.ModelGlue" /> <cfargument name="InstanceName" required="true" type="string" /> <cfset super.Init(arguments.ModelGlue) />
<!--- Controllers are in the application scope: Put any application startup code here. ---> <cfset variables.userGateway = createObject("component", "model.userGateway").init(getModelGlue().getConfigSetting("dsn"))> <cfset variables.userDAO = createObject("component", "model.userDAO").init(getModelGlue().getConfigSetting("dsn"))>
<cfreturn this /> </cffunction>
The new lines here are the ones creating variables.userGateway and variables.userDAO. In general these are just simple createObject() calls. But notice how I get the DSN setting:
Where did this value came from? The ModelGlue.xml file has a config setting on top. Normally you use this to define how ModelGlue will work with your application. You can use it to turn off debugging, define caching, etc. You can also add your own values. I've added this to the config block:
<!-- Photo Gallery Settings --> <setting name="dsn" value="PhotoGallery" />
Once I've done that, my Controller can use it as described above. By the way, I mentioned this code in an earlier entry's summary, but it was never actually in the entry. Sorry for the confusion.
So everything is ready. If you try to logon, you won't get an error. But of course, since the database is empty, you won't ever be able to logon. I've added a username/password combo for "admin" that will let you logon. You can test this here.
- As mentioned above, the last entry focused on the user model, and this entry focused on the Model-Glue hookup to that model.
- I first added an event to respond to the logon attempt.
- This event called an authenticate method in the controller file.
- If you successfully logon, I create a session variable. This same session variable is picked up by the getAuthenticated method which the Home method, and our later methods, will use.
- I added a DSN setting to the config file. The controller uses this when creating my model CFC instances.
- All in all, we have now hooked up the view, controller, and model, and hey, isn't that the point! The rest is just details!
By the way, this time I really did include the SQL file in the zip. Our folks ok so far? Am I going too slow, too fast? Skipping over stuff? Let me know!