= Ldaptic
This is an object-oriented LDAP wrapper library I started back in 2007 but
only recently polished up and released. It's unique in that it creates a
class hierarchy (in a namespace your provide) that exactly mirrors the class
hierarchy on the server. For example, on a typical server, you'll get an
+InetOrgPerson+ class which inherits from +OrganizationalPerson+ which
inherits from +Person+ which inherits from +Top+. You can reopen any of these
classes to add additional client side behavior.
Ldaptic started as mainly a tool to interact with my company's Active
Directory server, and I lost interest in it when I left that job. Recently,
I've become motivated to work on it again, as some of the blocking issues I
faced are now potentially solvable with Active Model.
== Getting Started
You need to have either the ruby-ldap or net-ldap gem installed. The former
is preferred because it's faster native C. Ldaptic is configured by including
a dynamically created module into a namespace of your choosing.
module Example
include Ldaptic::Module(
:adapter => :ldap_conn,
:base => 'ou=Users,dc=example,dc=com',
:host => 'example.com',
:username => 'cn=admin,ou=Users,dc=example,dc=com',
:password => 'password'
)
end
The adapter can usually be omitted as it defaults to :ldap_conn or :net_ldap,
based on which of the above two gems can be found. If the base is omitted, it
will use the first naming context on the server (usually what you want).
Entries are retrieved using the search method. Named parameters include
:base, :scope, :filter, :attributes, :scope, and :limit. All are optional.
entries = Example.search(
:filter => {:objectClass => 'inetOrgPerson'},
:limit => 10
)
A Ruby class is created for each objectClass defined on the server. Entries
are instances of these classes.
entry = Example.find('cn=admin,ou=Users,dc=example,dc=com')
=> #<Example::InetOrgPerson cn=admin,ou=Users,dc=example,dc=com ...>
entry.class.superclass
=> Example::OrganizationalPerson
Predictably, entries have attribute readers and writers.
entry.cn
=> <["admin"]>
entry.cn = "root"
entry[:cn]
=> <["root"]>
entry[:cn] = "admin"
The returned object is an attribute set and is similar to an array. Some
attributes are marked by the server as "single value;" those will return the
first element on method access but an attribute set on indexing access, for
programmatic convenience.
entry.uidNumber
=> 0
entry[:uidNumber]
=> <[0]>
The indexing syntax can also be used to create and fetch children.
users
=> #<Example::OrganizationalUnit ou=Users,dc=example,dc=com ...>
users[:cn=>'admin'] = Example::InetOrgPerson.new
=> #<Example::InetOrgPerson cn=admin,ou=Users,dc=example,dc=com ...>
users[:cn=>'admin']
=> #<Example::InetOrgPerson cn=admin,ou=Users,dc=example,dc=com ...>
Entry also implements many of the standard methods you've come to expect in
an Active Record world (save, valid?, errors, to_param, attributes, ...).
In fact, it is fully Active Model compliant.
For more information, see in particular Ldaptic::Methods (for namespace
methods like search), Ldaptic::Entry, and Ldaptic::AttributeSet.
== To Do
-
The test suite (reflecting my fledgling testing abilities from 2007) is more
smoke test than BDD. Perhaps switch to RSpec in the quest to rectify this.
-
Potential new features (mostly along the lines of "make it more like Active
Record") are in the GitHub issue tracker. Vote for and comment on the ones
you would find useful, as most are on hold until someone has a real use
case.