Class: Entitlements::Util::Util

Inherits:
Object
  • Object
show all
Includes:
Contracts::Core
Defined in:
lib/entitlements/util/util.rb

Constant Summary collapse

C =
::Contracts

Class Method Summary collapse

Class Method Details

.absolute_path(path) ⇒ Object



185
186
187
188
189
# File 'lib/entitlements/util/util.rb', line 185

def self.absolute_path(path)
  return path if path.start_with?("/")
  entitlements_config_dirname = File.dirname(Entitlements.config_file)
  File.expand_path(path, entitlements_config_dirname)
end

.any_to_cn(obj) ⇒ Object

Raises:

  • (ArgumentError)


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/entitlements/util/util.rb', line 101

def self.any_to_cn(obj)
  if obj.is_a?(Entitlements::Models::Group)
    return obj.cn.downcase
  end

  if obj.is_a?(String) && obj.start_with?("cn=")
    return Entitlements::Util::Util.first_attr(obj).downcase
  end

  if obj.is_a?(String)
    return obj
  end

  message = "Could not determine a common name from #{obj.inspect}!"
  raise ArgumentError, message
end

.camelize(str) ⇒ Object



139
140
141
142
143
144
# File 'lib/entitlements/util/util.rb', line 139

def self.camelize(str)
  result = str.split(/[\W_]+/).collect! { |w| w.capitalize }.join

  # Special cases
  result.gsub("Github", "GitHub").gsub("Ldap", "LDAP")
end

.decamelize(str) ⇒ Object



152
153
154
# File 'lib/entitlements/util/util.rb', line 152

def self.decamelize(str)
  str.gsub("GitHub", "Github").gsub("LDAP", "Ldap").gsub(/([a-z\d])([A-Z])/, "\\1_\\2").downcase
end

.dns_for_ou(ou, cfg_obj) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/entitlements/util/util.rb', line 191

def self.dns_for_ou(ou, cfg_obj)
  results = []
  path = path_for_group(ou)
  Dir.glob(File.join(path, "*")).each do |filename|
    # If it's a directory, skip it for now.
    if File.directory?(filename)
      next
    end

    # If the file is ignored (e.g. documentation) then skip it.
    if Entitlements::IGNORED_FILES.member?(File.basename(filename))
      next
    end

    # Determine the group DN. The CN will be the filname without its extension.
    file_without_extension = File.basename(filename).sub(/\.\w+\z/, "")
    unless file_without_extension =~ /\A[\w\-]+\z/
      raise "Illegal LDAP group name #{file_without_extension.inspect} in #{ou}!"
    end
    group_dn = ["cn=#{file_without_extension}", cfg_obj.fetch("base")].join(",")

    results << group_dn
  end

  results
end

.downcase_first_attribute(dn) ⇒ Object



16
17
18
19
# File 'lib/entitlements/util/util.rb', line 16

def self.downcase_first_attribute(dn)
  return dn.downcase unless dn =~ /\A([^=]+)=([^,]+),(.+)\z/
  "#{Regexp.last_match(1)}=#{Regexp.last_match(2).downcase},#{Regexp.last_match(3)}"
end

.first_attr(name_in) ⇒ Object



28
29
30
# File 'lib/entitlements/util/util.rb', line 28

def self.first_attr(name_in)
  name_in =~ /\A[^=]+=([^,]+),/ ? Regexp.last_match(1) : name_in
end

.parse_date(input) ⇒ Object

Raises:

  • (ArgumentError)


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/entitlements/util/util.rb', line 162

def self.parse_date(input)
  if input.is_a?(Date)
    return input
  end

  if input.is_a?(String)
    if input =~ /\A(\d{4})-?(\d{2})-?(\d{2})\z/
      return Date.new(Regexp.last_match(1).to_i, Regexp.last_match(2).to_i, Regexp.last_match(3).to_i)
    end

    raise ArgumentError, "Unsupported date format #{input.inspect} for parse_date!"
  end

  raise ArgumentError, "Unsupported object #{input.inspect} for parse_date!"
end

.path_for_group(group) ⇒ Object

Raises:

  • (Errno::ENOENT)


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/entitlements/util/util.rb', line 77

def self.path_for_group(group)
  unless Entitlements.config["groups"].key?(group)
    raise ArgumentError, "path_for_group: Group #{group.inspect} is not defined in the entitlements configuration!"
  end

  dir = Entitlements.config["groups"][group]["dir"]
  result_dir = if dir.nil?
    File.join(Entitlements.config_path, group)
  elsif dir.start_with?("/")
    dir
  else
    File.expand_path(dir, Entitlements.config_path)
  end

  return result_dir if File.directory?(result_dir)
  raise Errno::ENOENT, "Non-existing directory #{result_dir.inspect} for group #{group.inspect}!"
end

.remove_uids(obj, uids) ⇒ Object



126
127
128
129
130
131
# File 'lib/entitlements/util/util.rb', line 126

def self.remove_uids(obj, uids)
  return unless uids
  obj.delete_if do |uid|
    uids.member?(uid.downcase) || uids.member?(Entitlements::Util::Util.first_attr(uid).downcase)
  end
end

.validate_attr!(spec, data, text) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/entitlements/util/util.rb', line 40

def self.validate_attr!(spec, data, text)
  spec.each do |attr_name, config|
    # Raise if required attribute is not present.
    if config[:required] && !data.key?(attr_name)
      raise "#{text} is missing attribute #{attr_name}!"
    end

    # Skip the rest if the attribute isn't defined. (By the point the attribute is either
    # present or it's optional.)
    next unless data.key?(attr_name)

    # Make sure the attribute has the proper data type. Return when a match occurs.
    correct_type = [config[:type]].flatten.select { |type| data[attr_name].is_a?(type) }
    unless correct_type.any?
      existing = data[attr_name].class.to_s
      expected = [config[:type]].flatten.map { |clazz| clazz.to_s }.join(", ")
      raise "#{text} attribute #{attr_name.inspect} is supposed to be #{config[:type]}, not #{existing}!"
    end
  end

  extra_keys = data.keys - spec.keys
  if extra_keys.any?
    extra_keys_text = extra_keys.join(", ")
    raise "#{text} contains unknown attribute(s): #{extra_keys_text}"
  end

  nil
end