Permalink
Browse files

first commit, still mostly just code pulled from ad-schema

  • Loading branch information...
0 parents commit 88f8d535f165572621afea92f7d73237f46ba420 @jcredding jcredding committed Aug 16, 2011
@@ -0,0 +1,4 @@
+*.gem
+.bundle
+Gemfile.lock
+pkg/*
@@ -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"
@@ -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.
@@ -0,0 +1,7 @@
+include Rake::DSL
+
+require 'bundler'
+Bundler::GemHelper.install_tasks
+
+require 'assert/rake_tasks'
+Assert::RakeTasks.for :test
@@ -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
@@ -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
@@ -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
No changes.
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,5 @@
+module AD
+ module LDAP
+ VERSION = "0.0.1"
+ end
+end
@@ -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
Oops, something went wrong. Retry.

0 comments on commit 88f8d53

Please sign in to comment.