Confusion regarding variables.title and more - session

Please consider two files (I am working inside Sessions). Inside my .cfm page, I am creating an instance of a component and setting some values like following:
reports.cfm
<cfset LineChartObj = createObject("component", "#LocalSessionDotPath#.lib.report.testchart").init() />
<cfset LineChartObj.setTitle("Type of Events") />
<cfset LineChartObj.setYAxisTitle("Event Rate") />
testchart.cfc (relevant functions)
<cffunction name="setTitle" returntype="void" output="false" access="public" hint="Set title for chart">
<cfargument name="_Title" type="string" />
<cfset variables.title = arguments._Title >
</cffunction
<cffunction name="setXAxisTitle" returntype="void" output="false" access="public" hint="Set xAxisTitle for chart">
<cfargument name="_xAxisTitle" type="string" />
<cfset variables.xAxisTitle = arguments._xAxisTitle >
</cffunction>
<cffunction name="getXAxisTitle" returntype="string" access="public" hint="Get xAxisTitle of chart">
<cfreturn variables.xAxisTitle>
</cffunction>
My questions are:
The function name defined as "_Title" in setTitle() function can be anything, right? Not mandatory to take "_Title" ?
In <cfset variables.title = arguments._Title >, from where does the variables.title came from. Does it has something to do with session scope?

Right. Whatever the name you use for the argument defines the name you need to use to refer to it in your function body.
The variables scope is the default 'private' scope of storing variables & functions in a CFC. The code just explicitly declare to store title in the variables scope.
http://help.adobe.com/en_US/ColdFusion/10.0/Developing/WSc3ff6d0ea77859461172e0811cbec09af4-7ff1.html

Related

If user logoff or their session times out how to end coldfusion session?

I have system that I built and for this project I used Ajax with JQuery. On back end I use ColdFusion and session management to handle users session variables. There is two situations (actually three if we consider closing the browser) where users session will end. One situation is if they click Logout then I have function that will clear SESSION scope with all information in it but session is not ended. Also CFID and CFTOKEN are still the same. Here is example of Logout function:
<cffunction name="LogOut" access="remote" output="yes" returnformat="JSON" hint="Used in session timeout handling">
<cfset fnResults = structNew()>
<cfset dt = createODBCDateTime(now())>
<cfif structKeyExists(SESSION,"LoggedIn")>
<cfset temp = structClear(SESSION)>
<cfset fnResults.status = "200">
<cfelse>
<cfset fnResults.status = "400">
<cfset fnResults.message = "Error!">
</cfif>
<cfreturn fnResults>
</cffunction>
Second scenario is once user session timeout. Here is example of that fucntion:
<cffunction name="timeoutSession" access="remote" output="yes" verifyclient="no" securejson="false">
<cfset temp = structClear(SESSION)>
</cffunction>
Both of these functions will clear the session scope but not end the user session. I have used cfdump to check session scope once user logs out and CFID/CFTOKEN remains the same. I'm wondering how session cna be ended once they hit LogOut or timeoutSession function? Also should I rewrite the CFID and CFTOKEN every time user logs in the system? Here is example of my Application.cfc:
<cfcomponent output="false">
<cfset THIS.name = "MyApplication">
<cfset THIS.sessionManagement = true>
<cfset THIS.applicationTimeout = CreateTimeSpan(0, 8, 0, 0)>
<cfset THIS.sessionTimeout = CreateTimeSpan(0, 2, 0, 0)>
<cfset THIS.requestTimeOut = "60">
<cffunction name="onApplicationStart" access="public" returntype="boolean" output="false">
<cfset APPLICATION.appStarted = now()>
<cfset APPLICATION.title = "My Application">
<cfset APPLICATION.functions = CreateObject("component","udfs").init()>
<cfset APPLICATION.sessionMinutes = 30>
<cfreturn true>
</cffunction>
<!--- Runs when your session starts --->
<cffunction name="OnSessionStart" access="public" returntype="void" output="false">
<!--- Clear the session. --->
<cfset StructClear( SESSION ) />
<!--- Set loggedin flag to false. --->
<cfset SESSION.loggedin = false>
<cfreturn />
</cffunction>
<!--- Run before the request is processed. --->
<cffunction name="onRequestStart" returnType="boolean" output="false">
<cfargument name="thePage" type="string" required="true">
<cfset REQUEST.appCode = 'SPA'>
<cfset REQUEST.appName = 'Single Page Application'>
<cfset var page = listLast(arguments.thePage,"/")>
<!---<cfset onApplicationStart()>--->
<cfif !listFindNoCase("Login.cfm,Authentication.cfc",page)>
<cfif !structKeyExists(SESSION, "loggedin") OR SESSION.loggedin EQ false>
<cflocation url="Login.cfm" addToken="false">
</cfif>
</cfif>
<cfreturn true>
</cffunction>
</cfcomponent>
I'm not sure if session can be ended in Application.cfc or I have to do that in my cffunctions. Same for CFID and CFTOKEN what is the best place to set new values if user logs in again? If aynone have experience with this please let me know. I'm trying to prevent user to use the same session and raise level of security in my SPA.

ColdFusion - Capture Login Date / Time and Logout Date / Time

I want to know if there is a way to capture a users id when their session times out. I can capture if they click a logout button. I just want to be able to capture if their session times out.
Added this below
<cffunction name="onSessionEnd" access="public" returntype="void">
<cfquery name="logout" datasource="#application.datasource#">
update user
set logout_date = CURRENT_TIMESTAMP
where profile_id = #session.user_id#
</cfquery>
<cfreturn true />
</cffunction>
So I did the above It is not recording the logout date when the session times out.
Adding this comment as an answer for better formatting
Leigh deserves the credit. If you add your answer I will remove this one in favor of yours.
Given the example that you just added to your answer, you are doing it wrong. As Leigh pointed out in his comments you need to reference the session scope differently inside the OnSessionEnd method.
You are also missing the arguments for the OnSessionEnd method.
You will probably also want to make sure the variables are defined before trying to use them.
You should also use <cfqueryparam> within your queries.
Put it all together and it should look something like this:
<cffunction name="OnSessionEnd" access="public" returntype="void" output="false">
<cfargument name="SessionScope" type="struct" required="true" />
<cfargument name="ApplicationScope" type="struct" required="false" default="#StructNew()#" />
<cfif StructKeyExists(ARGUMENTS.ApplicationScope,"datasource") AND StructKeyExists(ARGUMENTS.SessionScope,"user_id")>
<cfquery name="local.logout" datasource="#ARGUMENTS.ApplicationScope.datasource#">
update user
set logout_date = CURRENT_TIMESTAMP
where profile_id = <cfqueryparam cfsqltype="cf_sql_integer" value="#ARGUMENTS.SessionScope.user_id#" />
</cfquery>
<cfelse>
<!--- variables are not defined, do something else here? --->
</cfif>
<cfreturn />
</cffunction>
Also, the request scope is not available within this method because it is not called by a request.
So had to change the application variable to a session variable only one that worked for me.
<cffunction name="onSessionEnd" access="public" returntype="void">
<cfquery name="logout" datasource="#session.datasource#">
update user
set logout_date = CURRENT_TIMESTAMP
where profile_id = #session.user_id#
</cfquery>
<cfreturn true />
</cffunction>

Why is onSessionStart() not run before onRequestStart()?

Assume the following site architecture:
/Application.cfc
/index.cfm
/sub/Application.cfc
/sub/index.cfm
/login/index.cfm
Now, here's some really basic pseudo-code:
/Application.cfc:
<cffunction name="onSessionStart" returntype="Void" output="false">
<cfscript>
SESSION.IsLoggedIn = false;
return;
</cfscript>
</cffunction>
<cffunction name="onRequestStart" returnType="Boolean" output="false">
<cfargument name="targetPage" type="string" required="true">
<cfscript>
if (SESSION.IsLoggedIn)
REQUEST.Cart = {};
</cfscript>
<cfreturn true />
</cffunction>
/sub/Application.cfc
<cffunction name="onRequestStart" returnType="Boolean" output="false">
<cfargument name="targetPage" type="string" required="true">
<cfscript>
SUPER.onRequestStart(ARGUMENTS.targetpage);
</cfscript>
<cfif NOT SESSION.IsLoggedIn>
<cflocation url="/login/" addtoken="false" />
</cfif>
<cfreturn true />
</cffunction>
When I request /sub/index.cfm, I get the following exception: Element ISLOGGEDIN is undefined in a Java object of type class [Ljava.lang.String;.
On my local development machine, I have Debugging Information turned on, so I can see that the SESSION is initialized, at least from a cookie standpoint, but, as you can see, my SESSION variables is NOT initialized:
Session Variables:
cfid=149415
cftoken=b7740eb6d2219f83-619FF01B-78AC-C0A4-1997EC503DA43982
sessionid=PRUDENTIAL_2UA1130DBK_2_149415_b7740eb6d2219f83-619FF01B-78AC-C0A4-1997EC503DA43982
urltoken=CFID=149415&CFTOKEN=b7740eb6d2219f83-619FF01B-78AC-C0A4-1997EC503DA43982
I cannot understand why onRequestStart() is being called before onSessionStart(). Shouldn't onSessionStart() be called first?

How can I clear the ColdFusion template cache as part of a deployment?

I ran into an issue this morning after deploying of some files to a ColdFusion website/application.
I updated an existing CFC with some new code. The CFC has an init() method that returns the instantiated Object:
Original MyObject.cfc:
<cfscript>
VARIABLES.MyParam = "";
</cfscript>
<cffunction name="init" returntype="MyObject" output="false">
<cfargument name="MyParam" type="String" required="true" />
<cfscript>
VARIABLES.MyParam = ARGUMENTS.MyParam;
return THIS;
</cfscript>
</cffunction>
New MyObject.cfc:
<cfscript>
VARIABLES.MyParam = "";
</cfscript>
<cffunction name="init" returntype="MyObject" output="false">
<cfargument name="MyParam" type="String" required="true" />
<cfscript>
setMyParam(ARGUMENTS.MyParam);
return THIS;
</cfscript>
</cffunction>
<cffunction name="setMyParam" output="false" returntype="Void">
<cfargument name="MyParam" type="String" required="true" />
<cfset VARIABLES.MyParam = Trim(ARGUMENTS.MyParam) />
</cffunction>
<cffunction name="getMyParam" output="false" returntype="String">
<cfreturn VARIABLES.MyParam />
</cffunction>
Any time an Object that extended this CFC called init(), it was throwing an exception:
"The value returned from the init function is not of type MyObject."
This issue did not occur in any of the other environments in which this change was deployed - only in Production.
The only thing that fixed it was clearing the template cache in ColdFusion Administrator.
So, I'm either looking for a way to prevent this from happening in the future and/or a way to automatically clear the template cache when I deploy files.
FYI, I currently deploy files using Tortoise SVN.
In your init() (or more preferably, in another reload-style method), programmatically call the Admin API's clearTrustedCache() method:
<cfscript>
// Login is always required (if the administrator password
// is enabled in the ColdFusion Administrator).
// This example uses two lines of code.
adminObj = createObject("component","cfide.adminapi.administrator");
adminObj.login("admin");
// Instantiate the runtime object.
myObj = createObject("component","cfide.adminapi.runtime");
// clear cache
myObj.clearTrustedCache();
// Stop and restart trusted cache. However, only the clearTrustedCache function needs to be called.
myObj.setCacheProperty("TrustedCache", 0);
myObj.setCacheProperty("TrustedCache", 1);
</cfscript>
This functionality's been in place as far back as CF7 (Source). Note that you will need the CF Admin password for this.
I would also recommend clearing the component cache, if you have that option enabled in your admin:
myObj.clearComponentCache();

ColdFusion & Ajax: Error Invoking CFC

I have tried multiple tutorials on this topic from Forta.com and yet run into the same error:
"Error invoking CFC/....(file path)../wgn.cfc: Internal Server Error [Enable
debugging by adding 'cfdebug to your URL parameters to see more info]"
I am working on my local machine and testing as localhost. Running WinXP Pro with sp3. Using Coldfusion's web server.
Both my .cfm and .cfc are in the same folder under the the webroot. In my case:
c:\ColdFusion9\wwwroot\bridges(.cfm and .cfc here)
So, they are in a "bridges" folder under wwwroot.
The code should generate some autosuggest functionality when the user types in the input box. Instead, it just spits back the above error.
This is my cfc named wgn.cfc:
<cfcomponent output="false">
<cfset THIS.dsn="bridges">
<!--- Lookup used for auto suggest --->
<cffunction name="getWGN" access="remote" returntype="array">
<cfargument name="search" type="any" required="false" default="">
<!--- Define variables --->
<cfset var data="">
<cfset var result=ArrayNew(1)>
<!--- Do search --->
<cfquery datasource="#THIS.dsn#" name="data">
SELECT tblIDs.ID
FROM tblIDs
WHERE (tblIDs.IDType = 'xxx') AND (tblIDs.ID Like ('#ARGUMENTS.search#%'));
</cfquery>
<!--- Build result array --->
<cfloop query="data">
<cfset ArrayAppend(result, searchIDs)>
</cfloop>
<!--- And return it --->
<cfreturn result>
</cffunction>
</cfcomponent>
And this is the relevant part of the form from my .cfm page:
<cfform .....>
<cfinput name="searchIDs" type="text" autosuggest="cfc:wgn.getWGN({cfautosuggestvalue})">
//......more to form, obviously
</cfform>
UPDATE
Solution:
change
<cfset ArrayAppend(result, searchIDs)>
to
<cfset ArrayAppend(result, ID)>

Resources