Last active
December 28, 2015 05:29
-
-
Save XORwell/7449960 to your computer and use it in GitHub Desktop.
ActiveLdap Extensions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
extracted the dynamic finders: https://github.com/XORwell/activeldap-dynamic_finders