Updating an LDAP directory

The cfldap tag lets you do the following to LDAP directory entries:

These actions let you manage LDAP directory contents remotely.

The following sections show how to build a ColdFusion page that lets you manage an LDAP directory:

The form displays directory entries in a table and includes a button that lets you populate the form fields based on the unique user ID.

The example ColdFusion page does not add or delete entry attributes or change the DN. The sections "Adding and deleting attributes of a directory entry" and "Changing a directory entry's DN" describe these operations.

To keep the code short, this example has limitations that are not appropriate in a production application. In particular, it has the following limitations:

Adding a directory entry

When you add an entry to an LDAP directory, you specify the DN, all the required attributes, including the entry's object class, and any optional attributes. The following example builds a form that adds an entry to an LDAP directory.

To add an entry:

  1. Create a file that looks like the following:
    <!--- set the LDAP server ID, user name, and password as variables
      here so they can be changed in only one place --->
    <cfset myServer="ldap.myco.com">
    <cfset myUserName="cn=Directory Manager">
    <cfset myPassword="password">
    
    <!--- Initialize the values used in form fields to empty strings --->
    <cfparam name="fullNameValue" default="">
    <cfparam name="surnameValue" default="">
    <cfparam name="emailValue" default="">
    <cfparam name="phoneValue" default="">
    <cfparam name="uidValue" default="">
    
    <!---When the form is submitted, add the LDAP entry --->
    <cfif isdefined("Form.action") AND Trim(Form.uid) IS NOT "">
      <cfif Form.action is "add">
        <cfif Trim(Form.fullName) is "" OR Trim(Form.surname) is ""
          OR Trim(Form.email) is "" OR Trim(Form.phone) is "">
            <h2>You must enter a value in every field.</h2>
            <cfset fullNameValue=Form.fullName>
            <cfset surnameValue=Form.surname>
            <cfset emailValue=Form.email>
            <cfset phoneValue=Form.phone>
            <cfset uidValue=Form.uid>
        <cfelse>
          <cfset attributelist="objectclass=top, person,
              organizationalperson, inetOrgPerson;
            cn=#Trim(Form.fullName)#; sn=#Trim(Form.surname)#;
            mail=#Trim(Form.email)#; 
            telephonenumber=#Trim(Form.phone)#;
            ou=Human Resources;
            uid=#Trim(Form.uid)#">
          <cfldap action="add"
            attributes="#attributeList#"
            dn="uid=#Trim(Form.uid)#, ou=People, o=Airius.com"
            server=#myServer#
            username=#myUserName#
            password=#myPassword#>
          <cfoutput><h3>Entry for User ID #Form.uid# has been added</h3>
          </cfoutput>
        </cfif>
      </cfif>  
    </cfif>
    
    <html>
    <head>
      <title>Update LDAP Form</title>
    </head>
    <body>
    <h2>Manage LDAP Entries</h2>
    
    <cfform action="update_ldap.cfm" method="post">
      <table>
        <tr><td>Full Name:</td>
          <td><cfinput type="Text"
             name="fullName"
             value=#fullNameValue#
             size="20"
             maxlength="30"
             tabindex="1"></td>
        </tr>
        <tr><td>Surname:</td> 
          <td><cfinput type="Text"
            name="surname"
            Value= "#surnameValue#"
            size="20"
            maxlength="20"
            tabindex="2"></td>
        </tr>
        <tr>
          <td>E-mail Address:</td>
          <td><cfinput type="Text"
            name="email"
            value="#emailValue#"
            size="20"
            maxlength="20"
            tabindex="3"></td>
        </tr>
        <tr>
          <td>Telephone Number:</td>
          <td><cfinput type="Text"
            name="phone"
            value="#phoneValue#"
            size="20"
            maxlength="20"
            tabindex="4"></td>
        </tr>
        <tr>
          <td>User ID:</td>
          <td><cfinput type="Text"
            name="uid"
            value="#uidValue#"
            size="20"
            maxlength="20"
            tabindex="5"></td>
        </tr>
        <tr>
          <td colspan="2">
            <input type="Submit"
             name="action"
             value="Add"
             tabindex="8"></td>
        </tr>
      </table>
      <br>
      *All fields are required for Add<br>
    </cfform>
    
    <!---Output the user list --->
    <h2>User List for the Human Resources Department</h2>
    <cfldap name="GetList"
      server=#myServer#
      action="query"
      attributes="cn,sn,mail,telephonenumber,uid"
      start="o=Airius.com"
      scope="subtree"
      filter="ou=Human Resources"
      sort="sn,cn"
      sortControl="asc, nocase">
    
    <table border="1">
      <tr>
        <th>Full Name</th>
        <th>Surname</th>
        <th>Mail</th>
        <th>Phone</th>
        <th>UID</th>
      </tr>
      <cfoutput query="GetList">
      <tr>
        <td>#GetList.cn#</td>
        <td>#GetList.sn#</td>
        <td>#GetList.mail#</td>
        <td>#GetList.telephonenumber#</td>
        <td>#GetList.uid#</td>
      </tr>
      </cfoutput>
    </table>
    </body>
    </html>
    
  2. At the top of the file, change the myServer, myUserName, and myPassword variable assignments to values that are valid for your LDAP server.
  3. Save the page as update_ldap.cfm and run it in your browser.

Reviewing the code

The following table describes the code:
Code
Description
<cfset myServer="ldap.myco.com">
<cfset myUserName="cn=Directory
  Manager">
<cfset myPassword="password">
Initializes the LDAP connection information variables. Uses variables for all connection information so that any changes have to be made in only one place.
<cfparam name="fullNameValue"
  default="">
<cfparam name="surnameValue" 
  default="">
<cfparam name="emailValue" 
  default="">
<cfparam name="phoneValue" 
  default="">
<cfparam name="uidValue" default="">
Sets the default values of empty strings for the form field value variables. The data entry form uses cfinput fields with value attributes so that the form can be prefilled and so that, if the user submits an incomplete form, ColdFusion can retain any entered values in the form when it redisplays the page.
<cfif isdefined("Form.action") AND Trim(Form.uid) IS NOT "">
Ensures that the user entered a User ID in the form.
<cfif Form.action is "add">
If the user clicks Add, processes the code that follows.
<cfif Trim(Form.fullName) is ""
  OR Trim(Form.surname) is ""
  OR Trim(Form.email) is "" 
  OR Trim(Form.phone) is "">
    <h2>You must enter a value in every
      field.</h2>
    <cfset fullNameValue=
      Form.fullName>
    <cfset surnameValue=
      Form.surname>
    <cfset emailValue=Form.email>
    <cfset phoneValue=Form.phone>
    <cfset uidValue=Form.uid>
If any field in the submitted form is blank, display a message and set the other form fields to display data that the user submitted.
<cfelse>
  <cfset attributelist=
    "objectclass=top,person,
      organizationalperson,
      inetOrgPerson;
    cn=#Trim(Form.fullName)#;
    sn=#Trim(Form.surname)#;
    mail=#Trim(Form.email)#; 
      telephonenumber=
    #Trim(Form.phone)#;
    ou=Human Resources;
    uid=#Trim(Form.uid)#">
If the user entered data in all fields, sets the attributelist variable to specify the entry's attributes, including the object class and the organizational unit (in this case, Human Resources).
The Trim function removes leading or trailing spaces from the user data.
  <cfldap action="add"
    attributes="#attributeList#"
    dn="uid=#Trim(Form.uid)#,
    ou=People, o=Airius.com"
    server=#myServer#
    username=#myUserName#
    password=#myPassword#>
  <cfoutput><h3>Entry for User ID
    #Form.uid# has been added</h3>
  </cfoutput>
</cfif>
</cfif>
</cfif>
Adds the new entry to the directory.
<cfform action="update_ldap.cfm"
     method="post">
  <table>
    <tr><td>Full Name:</td>
      <td><cfinput type="Text"
         name="fullName"
         value=#fullNameValue#
         size="20"
         maxlength="30"
         tabindex="1"></td>
    </tr>
.
.
.
    <tr><td colspan="2">
      <input type="Submit"
         name="action"
         value="Add"
         tabindex="6"></td>
    </tr>
  </table>
  <br>
  *All fields are required for Add<br>
</cfform>
Outputs the data entry form, formatted as a table. Each cfinput field always has a value, set by the value attribute when the page is called. The value attribute lets ColdFusion update the form contents when the form is redisplayed after the user clicks Add. The code that handles cases in which the user fails to enter all the required data uses this feature.
<cfldap name="GetList"
  server=#myServer#
  action="query"
  attributes="cn,sn,mail,
    telephonenumber,uid"
  start="o=Airius.com"
  scope="subtree"
  filter="ou=Human Resources"
  sort="sn,cn"
  sortControl="asc, nocase">
Queries the directory and gets the common name, surname, e-mail address, telephone number, and user ID from the matching entries.
Searches the subtree from the entry with the DN of o=Airius.com, and selects all entries in which the organizational unit is Human Resources.
Sorts the results by surname and then common name (to sort by last name, then first). Sorts in default ascending order that is not case-sensitive.
<table border="1">
  <tr>
  <th>Full Name</th>
  <th>Surname</th>
  <th>Mail</th>
  <th>Phone</th>
  <th>UID</th>
  </tr>
  <cfoutput query="GetList">
  <tr>
  <td>#GetList.cn#</td>
  <td>#GetList.sn#</td>
  <td>#GetList.mail#</td>
  <td>#GetList.telephonenumber#</td>
  <td>#GetList.uid#</td>
  </tr>
  </cfoutput>
</table>
</body>
</html>
Display the query results in a table.

Deleting a directory entry

To delete a directory entry, you must specify the entry DN.

The following example builds on the code that adds an entry. It adds Retrieve and Delete buttons. The Retrieve button lets you view a user's information in the form before you delete it.

To delete an entry:

  1. Open update_ldap.cfm, which you created in "Adding a directory entry".
  2. Between the first and second </cfif> tags, add the following code:
    <cfelseif Form.action is "Retrieve">
      <cfldap name="GetEntry"
        server=#myServer#
        action="query"
        attributes="cn,sn,mail,telephonenumber,uid"
        scope="subtree"
        filter="uid=#Trim(Form.UID)#"
        start="o=Airius.com">
      <cfset fullNameValue = GetEntry.cn[1]>
      <cfset surnameValue = GetEntry.sn[1]>
      <cfset emailValue = GetEntry.mail[1]>
      <cfset phoneValue = GetEntry.telephonenumber[1]>
      <cfset uidValue = GetEntry.uid[1]>
    <cfelseif Form.action is "Delete">
      <cfldap action="delete"
        dn="uid=#Trim(Form.UID)#, ou=People, o=Airius.com"
        server=#myServer#
        username=#myUserName#
        password=#myPassword#>
      <cfoutput><h3>Entry for User ID #Form.UID# has been deleted
    </h3></cfoutput>
    
  3. At the end of the code for the Add button (the input tag with Value=Add at the bottom of the form), delete the </td> end tag.
  4. After the end of the Add button input tag, add the following code:
      &nbsp
      <input type="Submit"
         name="action"
         value="Retrieve"
         tabindex="7">
      &nbsp
      <input type="Submit"
         name="action"
         value="Delete"
         tabindex="8"></td>
    
  5. Save the file and run it in your browser.

Reviewing the code

The following table describes the code:
Code
Description
<cfelseif Form.action is "Retrieve">
  <cfldap name="GetEntry"
    server=#myServer#
    action="query"
    attributes="cn,sn,mail,
      telephonenumber,uid"
    scope="subtree"
    filter="uid=#Trim(Form.UID)#"
    start="o=Airius.com">
  <cfset fullNameValue=
    GetEntry.cn[1]>
  <cfset surnameValue=GetEntry.sn[1]>
  <cfset emailValue=GetEntry.mail[1]>
  <cfset phoneValue=
    GetEntry.telephonenumber[1]>
  <cfset uidValue=GetEntry.uid[1]>
If the user clicks Retrieve, queries the directory and gets the information for the specified User ID.
Sets the form field's Value attribute to the corresponding query column.
This example uses the array index [1] to identify the first row of the GetEntry query object. Because the query always returns only one row, the index can be omitted.
<cfelseif Form.action is "Delete">
  <cfldap action="delete"
    dn="uid=#Trim(Form.UID)#,
      ou=People, o=Airius.com"
    server=#myServer#
    username=#myUserName#
    password="password">
  <cfoutput><h3>Entry for User
    ID #Form.UID# has been
    deleted</h3></cfoutput>
The user clicks delete, deletes the entry with the specified User ID and informs the user that the entry was deleted.
&nbsp
<input type="Submit"
  name="action"
  value="Retrieve"
  tabindex="7">
&nbsp
<input type="Submit"
  name="action"
  value="Delete"
  tabindex="8"></td>
Displays submit buttons for the Retrieve and Delete actions.

Updating a directory entry

The cfldap tag lets you change the values of entry attributes. To do so, you specify the entry DN in the dn attribute, and list the attributes to change and their new values in the attributes attribute.

The following example builds on the code that adds and deletes an entry. It can update one or more of an entry's attributes. Because the UID is part of the DN, you cannot change it.

To update an entry:

  1. Open update_ldap.cfm, which you created in "Adding a directory entry".
  2. Between the cfelseif Form.action is "Retrieve" block and the </cfif> tag, add the following code:
    <cfelseif Form.action is "Update">
    <cfset attributelist="cn=#Trim(form.FullName)#; sn=#Trim(Form.surname)#; mail=#Trim(Form.email)#; 
      telephonenumber=#Trim(Form.phone)#">
    <cfldap action="modify"
      modifytype="replace"
      attributes="#attributeList#"
      dn="uid=#Trim(Form.UID)#, ou=People, o=Airius.com"
      server=#myServer#
      username=#myUserName#
      password=#myPassword#>  
    <cfoutput><h3>Entry for User ID #Form.UID# has been updated</h3>
    </cfoutput>
    
  3. At the end of the code for the Delete button (the input tag with Value=Delete) at the bottom of the form), delete the </td> mark.
  4. After the end of the Delete button input tag, add the following code:
    &nbsp
    <input type="Submit"
      name="action"
      value="Update"
      tabindex="9"></td>
    
  5. Save the file and run it in your browser.

Reviewing the code

The following table describes the code:
Code
Description
<cfelseif Form.action is "Update">
  <cfset attributelist="cn=#Trim
    (form.FullName)#; 
    sn=#Trim(Form.surname)#;
    mail=#Trim(Form.email)#; 
    telephonenumber=#Trim(Form.phone)#">
  <cfldap action="modify"
      modifytype="replace"
      attributes="#attributeList#"
        dn="uid=#Trim(Form.UID)#,
        ou=People, o=Airius.com"
      server=#myServer#
      username=#myUserName#
      password=#myPassword#>  
    <cfoutput><h3>Entry for User ID
      #Form.UID# has been updated</h3>
    </cfoutput>
If the user clicks Update, sets the attribute list to the form field values and replaces the attributes for the entry with the specified UID.
Displays a message to indicate that the entry was updated.
This code replaces all of the attributes in a form, without checking whether they are blank. A more complete example would check for blank fields and either require entered data or not include the corresponding attribute in the attributes string.
&nbsp
<input type="Submit"
  name="action"
  value="Update"
  tabindex="9"></td>
Defines the Submit button for the update action.

Adding and deleting attributes of a directory entry

The following table lists the cfldap tag attributes that you must specify to add and delete LDAP attributes in an entry:
Action
cfldap syntax
Add attribute to entry
dn = "entry dn"
action = "modify"
modifyType = "add"
attributes = "attribname=attribValue[;...]"
Delete attribute from entry
dn = "entry dn"
action = "modify"
modifyType = "delete"
attributes = "attribName[;...]"

You can add or delete multiple attributes in one statement. To do this, use semicolons to separate the attributes in the attribute string.

The following example specifies the description and seealso LDAP attributes:

attributes="description=Senior Technical Writer;seealso=writers"

You can change the character that you use to separate values of multivalued attributes in an attribute string. You can also change the character that separates attributes when a string contains multiple attributes. For more information, see "Specifying an attribute that includes a comma or semicolon".

You can add or delete attributes only if the directory schema defines them as optional for the entry's object class.

Changing a directory entry's DN

To change the DN of an entry, you must provide the following information in the cfldap tag:

dn="original DN"
action="modifyDN"
attributes="dn=new DN"

For example:

<cfldap action="modifyDN"
  dn="#old_UID#, ou=People, o=Airius.com"
  attributes="uid=#newUID#"
  server=#myServer#
  username=#myUserName#
  password=#myPassword#>

The new DN and the entry attributes must conform to the directory schema; therefore, you cannot move entries arbitrarily in a directory tree. You can only modify a leaf only. For example, you cannot modify the group name if the group has children.

Note:   LDAP v2 does not let you change entry DNs.

Comments