Class: Identizer::DirectoryEntry

Inherits:
Object
  • Object
show all
Defined in:
lib/identizer/directory_entry.rb

Overview

An LDAP-flavoured directory entry: an attribute bag (uid, cn, sn, givenName, mail, ou, memberOf, …) with a computed DN. This is the unit the directory stores and the web admin edits. β€˜to_identity` projects it onto the token- facing Identity, mapping LDAP attributes to standard OIDC claims.

Constant Summary collapse

DEFAULT_BASE_DN =
"dc=identizer,dc=local"
DEFAULT_OU =
"people"
CLAIM_MAP =

LDAP attribute -> OIDC claim mapping for the token projection.

{
  "givenName" => "given_name",
  "sn" => "family_name",
  "cn" => "name",
  "memberOf" => "groups",
  "uid" => "preferred_username"
}.freeze
EDITABLE_ATTRIBUTES =

Attributes surfaced as editable fields in the web admin (in order).

%w[mail uid givenName sn cn ou memberOf].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(attributes = {}, base_dn: DEFAULT_BASE_DN) ⇒ DirectoryEntry

Returns a new instance of DirectoryEntry.



26
27
28
29
30
# File 'lib/identizer/directory_entry.rb', line 26

def initialize(attributes = {}, base_dn: DEFAULT_BASE_DN)
  @base_dn = base_dn
  @attributes = normalize(attributes)
  backfill!
end

Instance Attribute Details

#attributesObject (readonly)

Returns the value of attribute attributes.



24
25
26
# File 'lib/identizer/directory_entry.rb', line 24

def attributes
  @attributes
end

Class Method Details

.from(value, base_dn: DEFAULT_BASE_DN) ⇒ Object



32
33
34
35
36
37
# File 'lib/identizer/directory_entry.rb', line 32

def self.from(value, base_dn: DEFAULT_BASE_DN)
  return value if value.is_a?(DirectoryEntry)

  attributes = value.is_a?(Hash) ? value : { "mail" => value }
  new(attributes, base_dn: base_dn)
end

Instance Method Details

#[](key) ⇒ Object



39
40
41
# File 'lib/identizer/directory_entry.rb', line 39

def [](key)
  @attributes[key.to_s]
end

#custom_attributesObject

Attributes beyond the standard editable set β€” provider-specific names a SP might expect (e.g. custom_1, department). Emitted verbatim as claims.



50
51
52
# File 'lib/identizer/directory_entry.rb', line 50

def custom_attributes
  @attributes.except(*EDITABLE_ATTRIBUTES)
end

#dnObject



54
55
56
# File 'lib/identizer/directory_entry.rb', line 54

def dn
  "uid=#{uid},ou=#{ou},#{@base_dn}"
end

#groupsObject



46
# File 'lib/identizer/directory_entry.rb', line 46

def groups = Array(self["memberOf"]).reject { |group| group.to_s.empty? }

#mailObject



43
# File 'lib/identizer/directory_entry.rb', line 43

def mail = self["mail"]

#ouObject



45
# File 'lib/identizer/directory_entry.rb', line 45

def ou = self["ou"] || DEFAULT_OU

#to_hObject



69
70
71
# File 'lib/identizer/directory_entry.rb', line 69

def to_h
  @attributes
end

#to_identityObject

Token-facing projection: email + OIDC-mapped claims (+ dn).



59
60
61
62
63
64
65
66
67
# File 'lib/identizer/directory_entry.rb', line 59

def to_identity
  claims = { "dn" => dn }
  @attributes.each do |key, value|
    next if %w[mail userPassword].include?(key)

    claims[CLAIM_MAP[key] || key] = value
  end
  Identity.new(email: mail, sub: dn, claims: claims)
end

#uidObject



44
# File 'lib/identizer/directory_entry.rb', line 44

def uid = self["uid"]