4 Replies Latest reply: May 7, 2006 4:01 AM by BKBK RSS

    CFC question

    Hydrowizard Community Member
      I´m trying to get my head around cfcs. I have two functions. The login function -authenticate-works fine. I have another function-authorize-that gets the groupID of the user who has just logged in. I don´t understand how to output this. In the cfinvoke tag on index.cfm component I have returnVariable="groupID" and groupID="#getUserGroups.groupID#" but I get an error. Maybe I am missing an argument or something. Thanks for any advice.

      index.cfm
      <cfparam name="form.username" default="">

      <!--- Check for form submission --->
      <cfif structKeyExists(form,"checkAuth")>
      <!--- The user pressed the authenticate button --->
      <cfinvoke
      component="security"
      method="authenticate"
      returnVariable="authenticated"
      cfcUsername="#form.username#"
      cfcPassword="#form.password#">
      <cfif len(variables.authenticated)>
      <!--- now get their groupID --->
      <cfinvoke component="security"
      method="authorize"
      returnVariable="groupID"
      groupID="#getUserGroups.groupID#">
      </cfif></cfif>


      <cfif isDefined("variables.authenticated")>
      <cfif variables.authenticated NEQ 0>
      <b>Username and Password Authenticated Successfully!
      <cfoutput>#variables.groupID#</cfoutput></b>
      <cfinvoke
      component="security"
      method="authorize"
      returnVariable="authorize"
      cfcUsername="#form.username#">
      <cfelse>
      <b>Username and/or Password was incorrect!</b>
      </cfif>
      </cfif>

      <form name="checkAuth" method="post" action="index1.cfm">
      <br> <b>Email:</b>
      <input name="username" type="Text" class="ftforminputsmall" tabindex="1"

      maxlength="50">
      <b>Password:</b>
      <input name="password" type="password" class="ftforminputsmall" maxlength="50" tabindex="2">
      <input tabindex="3" type="Submit" name="checkAuth" class="ftforminputsmall">



      security.cfc
      <cfcomponent>
      <cffunction access="public" name="authenticate" output="0">
      <!--- security authentication function --->
      <!--- username and password required --->
      <cfargument name="cfcUsername" type="string" required="1"/>
      <cfargument name="cfcPassword" type="string" required="1"/>

      <!--- query the SecurityDB for the passed username and password --->
      <cfquery name="checkAuthentication" datasource="SecurityDB" username="root" password="riveravon">
      SELECT username, userID, totallogins, lastIP, lastbrowser, lastlogin
      FROM Security
      WHERE username = '#arguments.cfcUsername#'
      AND password = '#arguments.cfcPassword#'
      </cfquery>

      <!--- return the appropriate result --->
      <cfif checkAuthentication.recordCount>

      <!--- check the users security groups so we can see what groupID and therefore access level they have --->
      <cfquery name="getUserGroups" datasource="SecurityDB" username="root" password="riveravon">
      SELECT security_groups.groupID, groups.groupID
      FROM groups, security_groups
      WHERE groups.groupID = security_groups.groupID
      AND security_groups.username = '#arguments.cfcUsername#'
      </cfquery>

      <cfreturn checkAuthentication.username/>

      <cfelse>
      <cfreturn 0/>
      </cfif>
      </cffunction>


      <cffunction access="public" name="authorize" output="0">
      <!--- security function finding what groupID and therefore access level--->
      <!--- username from login form used to check group IDs --->
      <cfargument name="cfcUsername" type="string" required="1"/>

      <!--- query the SecurityDB and get all group id for the passed username --->
      <cfquery name="getUserGroups" datasource="SecurityDB" username="root" password="riveravon">
      SELECT groupID
      FROM Security_Groups
      WHERE username = '#arguments.cfcUsername#'
      </cfquery>


      <!--- return the appropriate groupID(s) --->
      <cfif getUserGroups.recordCount>
      <cfreturn getUserGroups.groupID/>
      <cfelse>
      <cfreturn 0/>
      </cfif>
      </cffunction>
      </cfcomponent>
        • 1. CFC question
          BKBK CommunityMVP
          1) Most of the end-tags are unnecessary. For example, you may use <cfreturn getUserGroups.groupID> in place of <cfreturn getUserGroups.groupID />. In any case, it is advisable to have a space before such an end-tag slash.

          2) If a function returns, you must declare its return type
          <cffunction access="public" name="authorize" output="0" returntype="string">
          <cffunction access="public" name="authenticate" output="0" returntype="string">


          3) Modify the returned variables accordingly
          <!--- function "authenticate" --->
          <cfif checkAuthentication.recordCount>
          ...etc...
          <cfreturn checkAuthentication.username>
          <cfelse>
          <!--- Remember that you will be testing if Len(returnedVar) EQ 0 --->
          <cfreturn "">
          </cfif>
          <!--- function "authorize" --->
          <!--- return the appropriate groupID(s) --->
          <cfif getUserGroups.recordCount>
          <cfreturn getUserGroups.groupID>
          </cfif>
          <!--- if recordcount is 0, return blank string --->
          <cfreturn "">
          </cffunction>


          4) The following code contains two errors. It implies that groupID is an attribute of cfinvoke, which is not true. It also does not pass the required parameter, cfcUsername.
          <cfinvoke component="security"
          method="authorize"
          returnVariable="groupID"
          groupID="#getUserGroups.groupID#">


          I'm guessing your intention is to do
          <cfinvoke component="security" method="authorize" cfcUsername="#form.username#" returnVariable="grpID" />
          <cfset groupID="#grpID#"><!--- the returned string--->

          5) The following passage seems to repeat a theme
          <cfif structKeyExists(form,"checkAuth")>
          <!--- The user pressed the authenticate button --->
          <cfinvoke
          component="security"
          method="authenticate"
          returnVariable="authenticated"
          cfcUsername="#form.username#"
          cfcPassword="#form.password#">
          <cfif len(variables.authenticated)>
          <!--- now get their groupID --->
          <cfinvoke component="security"
          method="authorize"
          returnVariable="groupID"
          groupID="#getUserGroups.groupID#">
          </cfif></cfif>
          <cfif isDefined("variables.authenticated")>
          <cfif variables.authenticated NEQ 0>
          <b>Username and Password Authenticated Successfully!
          <cfoutput>#variables.groupID#</cfoutput></b>
          <cfinvoke
          component="security"
          method="authorize"
          returnVariable="authorize"
          cfcUsername="#form.username#">
          <cfelse>
          <b>Username and/or Password was incorrect!</b>
          </cfif>
          </cfif>


          Tighter is:

          <cfif structKeyExists(form,"checkAuth")>
          <cfinvoke
          component="security"
          method="authenticate"
          returnVariable="authenticated"
          cfcUsername="#form.username#"
          cfcPassword="#form.password#">

          <cfif len(variables.authenticated)>
          <b>Username and Password Authenticated Successfully!</b>
          <!--- now get their groupID --->
          <cfinvoke
          component="security"
          method="authorize"
          cfcUsername="#form.username#"
          returnVariable="grpID" />
          <!--- display returned string --->
          <cfif Len(grpID) GT 0>
          GroupID = <cfoutput>"#grpID#"</cfoutput>
          <cfelse>
          No GroupID for user
          </cfif>
          <cfelse>
          <b>Username and/or Password was incorrect!</b>
          </cfif>
          </cfif>

          6) Have you had a look at a previous suggestion for your CFC?





          added edit: correction for function, "authorize". It should return a string, the GroupID, not a query. Thanks, Hydrowizard.




          • 2. CFC question
            Hydrowizard Community Member
            Hi thanks a lot for the very complete answer BKBK.

            1) Most of the end-tags are unnecessary. For example, you may use <cfreturn getUserGroups.groupID> in place of <cfreturn getUserGroups.groupID />. In any case, it is advisable to have a space before such an end-tag slash.

            OK I put in spaces. The end tag is for xml right?

            2) If a function returns, you must declare its return type
            <cffunction access="public" name="authorize" output="0" returntype="query">
            <cffunction access="public" name="authenticate" output="0" returntype="string">

            I was getting errors on the returntype for authorize. I changed the returntype to string and also tried varchars as I got an error on returntype query.

            3) I get an error with the following code

            <!--- return the appropriate groupID(s) --->
            <cfif getUserGroups.recordCount>
            <cfreturn getUserGroups.groupID />
            <cfelse>
            <!--- if recordcount is 0, return "blank" query --->
            <cfset q = queryNew("blankColumn","varchar")>
            <cfreturn q />
            </cfif>
            </cffunction>

            Complex object types cannot be converted to simple values.
            The expression has requested a variable or an intermediate expression result as a simple value, however, the result cannot be converted to a simple value. Simple values are strings, numbers, boolean values, and date/time values. Queries, arrays, and COM objects are examples of complex values.
            The most likely cause of the error is that you are trying to use a complex value as a simple one. For example, you might be trying to use a query variable in a <CFIF> tag. This was possible in ColdFusion 2.0 but creates an error in later versions.


            I changed it back to cfreturn 0 and 0 is output on the index page:
            <!--- return the appropriate groupID(s) --->
            <cfif getUserGroups.recordCount>
            <cfreturn getUserGroups.groupID />
            <cfelse>
            <cfreturn 0 />
            </cfif>
            </cffunction>
            </cfcomponent>

            4) Works fine I have:
            <cfinvoke component="security"
            method="authorize"
            cfcUsername="#form.username#"
            returnVariable="grpID" />
            <cfset groupID="#grpID#">
            </cfif></cfif>


            5) What I have in my webpage at the moment works fine:
            <cfif isDefined("variables.authenticated")>
            <cfif variables.authenticated NEQ 0>
            <b>Username and Password Authenticated Successfully!
            <cfoutput>#variables.grpID#</cfoutput></b>
            <cfinvoke
            component="security"
            method="authorize"
            returnVariable="authorize"
            cfcUsername="#form.username#">
            <cfelse>
            <b>Username and/or Password was incorrect!</b>
            </cfif>
            </cfif>

            I get the following error with the code below: Element AUTHENTICATED is undefined in VARIABLES.

            <cfif len(variables.authenticated)>
            <b>Username and Password Authenticated Successfully!
            <cfoutput>#variables.grpID#</cfoutput></b>
            <cfinvoke
            component="security"
            method="authorize"
            returnVariable="authorize"
            cfcUsername="#form.username#">
            <!--- display returned query --->
            <cfif grpID.recordcount GT 0>
            <cfdump var="#grpID#">
            <cfelse>
            No GroupID for user
            </cfif>
            <cfelse> <b>Username and/or Password was incorrect!</b>
            </cfif>


            6) I am having a look at your earlier post in detail.
            • 3. CFC question
              BKBK CommunityMVP
              3) I get an error with the following code
              Yes, that is to be expected. It was on oversight. The two queries of the same name, getUserGroups, led to the confusion. Naturally, my thinking was, if a query returns more than one column then one has to return the query. But I see now that the other query of the same name returns a string, the user's groupID.

              It should indeed return a string. I would presume that there is just one GroupID per user. I have included the correction above.




              • 4. Re: CFC question
                BKBK CommunityMVP
                Oh, and, yeah. You're right about the need for an ending / in XML and XHTML.