Skip to content

Instantly share code, notes, and snippets.

@XORwell
Last active December 28, 2015 05:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save XORwell/7449960 to your computer and use it in GitHub Desktop.
Save XORwell/7449960 to your computer and use it in GitHub Desktop.
ActiveLdap Extensions
# ActiveLdapExtensions
#
# @author Christian Nennemann
#
module ActiveLdapExtensions
extend ActiveSupport::Concern
module Time
# Convert the time to the FILETIME format, a 64-bit value representing the
# number of 100-nanosecond intervals since January 1, 1601 (UTC).
def wtime
::Time.new.to_i * 10000000 + 116444736000000000
end
# Create a time object from the FILETIME format, a 64-bit value representing
# the number of 100-nanosecond intervals since January 1, 1601 (UTC).
def from_wtime(wtime)
::Time.at((wtime - 116444736000000000) / 10000000)
end
module_function :wtime, :from_wtime
end
included do
if self.superclass.eql?(ActiveLdap::Base)
class << self
#
# Pluck attributes
#
# @param [String|Symbol|Array] *attribute
#
# @return [Array] result
#
# @example pluck(:sn)
# @example pluck(:cn, :sn)
# @example pluck("cn", "sn")
def pluck(*attribute)
attribute = [attribute].flatten.map(&:to_s)
attribute.reject!(&:empty?)
return [] if attribute.empty?
attribute.map!{ |x| x == 'dn' ? 'distinguishedName' : x }
result = self.search(
attributes: attribute
).collect{ |_, v|
v.values
.flatten
}
return [] if result.uniq.flatten.empty?
result
end
# Convenience method to find
def where(attributes)
self.find(:all, filter: [:and, attributes])
end
def first_or_initialize(attributes)
self.where(attributes).first || new(attributes)
end
# Find entries with empty attribute value
#
def find_with_empty(attribute)
entries = self.pluck(:dn, attribute)
entries.select!{ |_, v|
v.nil?
}.flatten!
.reject!(&:nil?)
self.find(entries)
end
# Find all enabled accounts
#
# @return [Array] entries Array of LDAP::User objects
def find_all_enabled
self.find(:all, filter: [:or, [:or, {:userAccountControl => 66048}], {:userAccountControl => 512}])
end
# Find all disabled accounts
#
# @return [Array] entries Array of LDAP::User objects
def find_all_disabled
self.find(:all, filter: [:or, [:or, {:userAccountControl => 66050}], {:userAccountControl => 514}])
end
# Find all accounts with 'password never expires' flag
#
# @return [Array] entries Array of LDAP::User objects
def find_all_password_never_expires
self.find(:all, filter: {:userAccountControl => 66048} )
end
alias_method :password_never_expires, :find_all_password_never_expires
# Find all accounts with expired passwords
# @return [Array] entries Array of LDAP::User objects
def find_all_expired_passwords
# REVIEW: TEST IF THIS WILL WORK
self.find(:all, filter: {:userAccountControl => 8388608} )
end
alias_method :expired_passwords, :find_all_expired_passwords
end
end
# Return the time of next password expiration
# It'll simply add 90 days to pwdLastSet
# @param [Integer] advance_days (from last pwdSet)
# @return [Time] time
def pwd_expires(advance_days = 90)
ActiveLdapExtensions::Time.from_wtime(self.pwdLastSet.to_i).advance(:days => advance_days) if self.has_attribute?(:pwdLastSet)
end
# Return the time of last password change
# @return [Time] time
def pwd_last_set
ActiveLdapExtensions::Time.from_wtime(self.pwdLastSet.to_i) if self.has_attribute?(:pwdLastSet)
end
# Return object as hash
# @return [Hash] object
def to_hash
self.attributes
end
# Return object as json
# @return [Hash] object
def as_json
self.attributes.as_json
end
# Check UAC if account password expired
#
# @return [Boolean] password expired
def pwd_expired?
# TODO: Test if it'll work
[8388608].include?(self.userAccountControl)
end
alias_method :password_expired?, :pwd_expired?
# Check UAC if account is disabled
#
# 514 = Disabled
# 66050 = Disabled, password never expires
#
# @return [Boolean] account_disabled
def disabled?
[514, 66050].include?(self.userAccountControl)
end
# Check UAC if account is enabled
#
# 512 = Enabled
# 66048 = Enabled, password never expires
#
# @return [Boolean] account_disabled
def enabled?
[512, 66048].include?(self.userAccountControl)
end
end
end
# You can also use use objects as filter
ActiveLdap::Base.search(
attributes: ['cn', 'objectClass'],
base:"ou=Users,dc=example,dc=com",
scope: :sub,
classes: ['user'],
filter: Net::LDAP::Filter.ne('objectClass', 'computer') #<-- uses Net::LDAP::Filter
)
# You can combine filters
Net::LDAP::Filter.present("employeeID") & Net::LDAP::Filter.eq("objectClass", "person")
@XORwell
Copy link
Author

XORwell commented Nov 15, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment