A Sample Application

Ruby/ActiveLdap

...an object oriented interface to LDAP for Ruby on Rails...

A Sample Application
A Sample Application

A Sample Application

There is a demo available. Just Sign Up and Login!

  • Create a test application with rails:
    rails testapp cd testapp
  • Install the ActiveLdap plugin.
    cd testapp ./script/plugin install http://ruby-activeldap.googlecode.com/svn/trunk/rails/plugin/active_ldap/
  • Generate the config/ldap.yml file.
    ./script/generate scaffold_active_ldap
  • Edit config/ldap.yml so the application can access the ldap database:
    THE_PASSWORD="ldap123" # THE PASSWORD YOU ENTERED DURING slapd SETUP cat << HERE > config/ldap.yml development: host: 127.0.0.1 port: 389 base: dc=development,dc=nodomain bind_dn: cn=admin,dc=nodomain password: $THE_PASSWORD test: host: 127.0.0.1 port: 389 base: dc=test,dc=nodomain bind_dn: cn=admin,dc=nodomain password: $THE_PASSWORD production: host: 127.0.0.1 port: 389 method: :tls base: dc=production,dc=nodomain bind_dn: cn=admin,dc=nodomain password: $THE_PASSWORD HERE

Monitoring what slapd does

  • Start slapd in debugging mode, so you can see what it does. It helps understanding what is going on. Open a Konsole or Xterm and do:
    sudo /etc/init.d/slapd stop sudo slapd -d 65535
    You should see a lot of information scrolling past the screen. The last line should read something like:
    daemon: select: listen=7 active_threads=0 tvp=NULL
    From this window you can now monitor slapd and see what requests are being made from ActiveLdap.

Using irb to interact with ActiveLdap

  • Start irb:
    irb -rubygems
    Paste the following in to irb:
    require 'active_ldap' ActiveLdap::Base.establish_connection class User < ActiveLdap::Base ldap_mapping end User.connected? User.find(:all) class Thing < ActiveLdap::Base ldap_mapping end Thing.find(:all)
    If everything went well, you should search the output of slapd for strings like the following:
    conn=0 op=1 SRCH base="ou=Users" scope=2 deref=0 filter="(&(?=false)(objectClass=top))" conn=0 op=2 SRCH base="ou=Things" scope=2 deref=0 filter="(&(?=false)(objectClass=top))"
    So, if you make a class called 'Klass', then ActiveLdap will search for 'ou=Klasses" in the LDAP directory. You can change that behaviour by using the :prefix option to ldap_mapping:
    class Person < ActiveLdap::Base ldap_mapping :prefix => "sn=Smith" end Person.find(:all)
    In your slapd output:
    conn=0 op=1 SRCH base="sn=Smith" scope=2 deref=0 filter="(&(?=false)(objectClass=top))"

Designing your DIT

  • There are many ways you can construct your Directory Information Tree. (See the links below).
    We will settle for a simple tree with only 'ou=Users' and 'ou=Groups' directly under 'dc=development,dc=nodomain', for now.

development, test, production

  • A possible way to separate development, test and productions code is to add 'dc=development', 'dc=test', and 'dc=production' to the tree. You need to build your tree accordingly. Add these containers using slapadd. Beware to stop your ldapserver! (If you are using slapd in debug mode, press Ctrl-C, else use '/etc/init.d/slapd stop').
    cat << HERE > environments.ldif dn: dc=development,dc=nodomain objectClass: top objectClass: dcObject objectClass: organization o: development dc: development structuralObjectClass: organization description: The development environment dn: dc=test,dc=nodomain objectClass: top objectClass: dcObject objectClass: organization o: test dc: test structuralObjectClass: organization description: The test environment dn: dc=production,dc=nodomain objectClass: top objectClass: dcObject objectClass: organization o: production dc: production structuralObjectClass: organization description: The production environment HERE sudo slapadd -v -l environments.ldif
    You should see the succesful additions of these entries:
    added: "dc=development,dc=nodomain" (00000003) added: "dc=test,dc=nodomain" (00000004) added: "dc=production,dc=nodomain" (00000005)

Adding the 'Users' and 'Groups' containers.

  • Add Groups and Users containers using slapadd. Beware to stop your ldapserver! (If you are using slapd in debug mode, press Ctrl-C, else use '/etc/init.d/slapd stop').
    cat << HERE > users_and_groups_development.ldif dn: ou=Users,dc=development,dc=nodomain objectClass: top objectClass: organizationalUnit ou: Users description: Users dn: ou=Groups,dc=development,dc=nodomain objectClass: top objectClass: organizationalUnit ou: Groups description: Groups HERE sudo slapadd -v -l users_and_groups_development.ldif
    You should see the succesful additions of these entries:
    added: "ou=Users,dc=development,dc=nodomain" (00000006) added: "ou=Groups,dc=development,dc=nodomain" (00000007)

Generating models.

  • Generate your models with the model_active_ldap generator:
    ./script/generate model_active_ldap user
    You should see something like this:
    exists app/models/ exists test/unit/ exists test/fixtures/ create app/models/user.rb create test/unit/user_test.rb create test/fixtures/users.yml
    (For the group model, substitute group for user)

Generating a controller.

  • Generate your controllers with the controller generator. Yes, this is a rails controller; no Ruby/ActiveLdap magic involved (yet).
    ./script/generate controller group
    You should see something like this:
    exists app/controllers/ exists app/helpers/ create app/views/group exists test/functional/ create app/controllers/group_controller.rb create test/functional/group_controller_test.rb create app/helpers/group_helper.rb
    (For the user controller, substitute user for group)

    Download make-testapp.gz, a script that installs the testapp almost unattended.
    Use at your own risk.
    Add some functionality to your user controller:
    def index @users = User.find(:all) end
    The same aplies to the group controller:
    def index @groups = Group.find(:all) end
    Now you need some views... In app/views/user/index.rhtml
    <% if @users.empty? -%> <p><%= "No user." %></p> <% else -%> <ul> <% @users.each do |user| -%> <li><%= user_link(user, true) %></li> <% end -%> </ul> <% end -%>
    In app/views/group/index.rhtml, do the same but substitute group for user.

Start the webserver and test.

  • Start the webserver:
    ./script/server
    Point your browser to the correct location, i.e. http://127.0.0.1:3000/user
    You should see:
    No users
Developed with QwikZite (version 1.12)  (2008-06-16 09:52:54)