Skip to content
This repository has been archived by the owner on Dec 9, 2017. It is now read-only.

Commit

Permalink
first commit, still mostly just code pulled from ad-schema
Browse files Browse the repository at this point in the history
  • Loading branch information
jcredding committed Aug 16, 2011
0 parents commit 88f8d53
Show file tree
Hide file tree
Showing 14 changed files with 409 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
*.gem
.bundle
Gemfile.lock
pkg/*
7 changes: 7 additions & 0 deletions Gemfile
@@ -0,0 +1,7 @@
source "http://rubygems.org"

# Specify your gem's dependencies in ad-ldap.gemspec
gemspec

gem 'rake', '~>0.9.2'
gem "assert", :path => "~/Projects/work/gems/assert"
45 changes: 45 additions & 0 deletions README.textile
@@ -0,0 +1,45 @@
h1. AD::LDAP

A small wrapper to Net::LDAP to provide some extended functionality and utility.

h2. Description

AD::LDAP is a small wrapper to the Net::LDAP library. Net::LDAP provides a nice low-level interface
for interacting with an LDAP server. AD::LDAP simply wraps that interface and provides some
extended functionality through:

* Built-in logging of any communication with the LDAP server
* Easier use of net-ldap's search

h2. Installation

gem install ad-ldap

h2. Usage

TODO

h2. License

Copyright (c) 2011 Collin Redding, and Team Insight

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
7 changes: 7 additions & 0 deletions Rakefile
@@ -0,0 +1,7 @@
include Rake::DSL

require 'bundler'
Bundler::GemHelper.install_tasks

require 'assert/rake_tasks'
Assert::RakeTasks.for :test
25 changes: 25 additions & 0 deletions ad-ldap.gemspec
@@ -0,0 +1,25 @@
# -*- encoding: utf-8 -*-
$:.push File.expand_path("../lib", __FILE__)
require "ad-ldap/version"

Gem::Specification.new do |s|
s.name = "ad-ldap"
s.version = AD::LDAP::VERSION
s.authors = ["jcredding"]
s.email = ["TempestTTU@gmail.com"]
s.homepage = ""
s.summary = %q{TODO: Write a gem summary}
s.description = %q{TODO: Write a gem description}

s.rubyforge_project = "ad-ldap"

s.files = `git ls-files`.split("\n")
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
s.require_paths = ["lib"]

# specify any dependencies here; for example:
s.add_runtime_dependency "net-ldap"

s.add_development_dependency "mocha"
end
32 changes: 32 additions & 0 deletions lib/ad-ldap.rb
@@ -0,0 +1,32 @@
require 'ostruct'

require 'ad-ldap/adapter'
require 'ad-ldap/version'

module AD
module LDAP
class << self

def configure
yield self.config
end

def method_missing(method, *args, &block)
if self.adapter.respond_to?(method)
self.adapter.send(method, *args, &block)
else
super
end
end

def config
@config ||= OpenStruct.new
end

def adapter
@adapter ||= AD::LDAP::Adapter.new(self.config)
end

end
end
end
69 changes: 69 additions & 0 deletions lib/ad-ldap/adapter.rb
@@ -0,0 +1,69 @@
require 'net/ldap'

require 'ad-ldap/response'

module AD
module LDAP

class Adapter < ::Net::LDAP
attr_accessor :config

def initialize(config)
self.config = config
super({
:host => self.config.host,
:port => self.config.port,
:base => self.config.base,
:encryption => self.config.encryption
})
if self.config.auth
self.auth(self.config.auth.username, self.config.auth.password)
end
end

# don't raise when an open connection is already open, just yield it
def open
if @open_connection
yield @open_connection
else
super
end
end

[ :add, :delete, :modify ].each do |method|
define_method(method) do |args|
result = super
self.check_operation
result
end
end
[ :add_attribute, :replace_attribute ].each do |method|
define_method(method) do |dn, attribute, value|
result = super
self.check_operation
result
end
end
def delete_attribute(dn, attribute)
result = super
self.check_operation
result
end

def search(args = {})
results = super(args.dup)
self.check_operation
results
end

protected

def check_operation
check = self.get_operation_result
ActiveDirectory::LDAP::Response.new(check.code, check.message).handle!
end

end

end
end
Empty file added lib/ad-ldap/exceptions.rb
Empty file.
70 changes: 70 additions & 0 deletions lib/ad-ldap/logger.rb
@@ -0,0 +1,70 @@
module ActiveDirectory
module LDAP

# Inspired by https://github.com/tpett/perry logger
class Logger
attr_accessor :logger

def initialize(logger)
self.logger = logger
end

def out(method, args, result, time)
color = "4;32;1"
name = "%s (%.1fms)" % [ "LDAP", time ]
message = self.generate_message(method, args)
output = " \e[#{color}]#{name} #{message}\e[0m"
if self.logger
self.logger.debug(output)
else
puts output
end
end

protected

def delete(dn)
self.run(:delete, { :dn => dn })
end

def replace_attribute(dn, field, value)
self.run(:replace_attribute, dn, field, value)
end

def delete_attribute(dn, field)
self.run(:delete_attribute, dn, field)
end

def generate_message(method, args)
case(method.to_sym)
when :replace_attribute
dn, field, value = args
"#{method}(#{dn.inspect}, #{field.inspect}, #{self.filter_value(value, field)})"
when :delete_attribute
dn, field = args
"#{method}(#{dn.inspect}, #{field.inspect})"
else
"#{method}(#{self.filter_args(args.first)})"
end
end

FILTERED = [ /password/, /unicodePwd/ ]
def filter_args(args = {})
(args.inject({}) do |filtered, (key, value)|
filtered[key] = self.filter_value(value, key)
filtered
end).inspect
end
def filter_value(value, key)
case(key)
when *FILTERED
"[FILTERED]"
else
value.to_s
end
end

end

end
end
28 changes: 28 additions & 0 deletions lib/ad-ldap/response.rb
@@ -0,0 +1,28 @@
require 'ad-ldap/exceptions'

module ActiveDirectory
module LDAP

# descriptions: http://wiki.service-now.com/index.php?title=LDAP_Error_Codes
class Response
attr_accessor :code, :message

CODES = {
:success => 0
}.freeze

def initialize(code, message)
self.code = code.to_i
self.message = message
end

def handle!
if self.code != CODES[:success]
raise(AD::LDAP::Error, "#{self.code}: #{self.message}")
end
end

end

end
end
43 changes: 43 additions & 0 deletions lib/ad-ldap/search_args.rb
@@ -0,0 +1,43 @@
require 'net/ldap'

module ActiveDirectory
module LDAP

class SearchArgs < Hash

LDAP_KEYS = [ :base, :filter, :attributes, :return_result, :attributes_only,
:scope, :size ]

def initialize(args)
super()
conditions = {}
args.each do |key, value|
if LDAP_KEYS.include?(key.to_sym)
self[key.to_sym] = value
else
conditions[key.to_sym] = value
end
end
if !self[:filter] && (filters = self.build_filters(conditions))
self[:filter] = filters
end
end

protected

def build_filters(conditions = {})
conditions.inject(nil) do |filters, (key, value)|
field, operator = key.to_s.split("__")
operator ||= "eq"
if attribute = ActiveDirectory.config.attributes[field.to_sym]
field = (attribute.ldap_name || field)
end
filter = ::Net::LDAP::Filter.send(operator, field, value)
filters ? ::Net::LDAP::Filter.join(filters, filter) : filter
end
end

end

end
end
5 changes: 5 additions & 0 deletions lib/ad-ldap/version.rb
@@ -0,0 +1,5 @@
module AD
module LDAP
VERSION = "0.0.1"
end
end
13 changes: 13 additions & 0 deletions test/helper.rb
@@ -0,0 +1,13 @@
require 'mocha'

# add the current gem root path to the LOAD_PATH
root_path = File.expand_path("../..", __FILE__)
if !$LOAD_PATH.include?(root_path)
$LOAD_PATH.unshift(root_path)
end

require 'ad-ldap'

class Assert::Context
include Mocha::API
end

0 comments on commit 88f8d53

Please sign in to comment.