1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 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 217 218 219 220 221 222 223
|
module ActiveLdap
module Validations
extend ActiveSupport::Concern
include ActiveModel::Validations
module ClassMethods
def attribute_method?(attribute)
normalized_attribute = entry_attribute.normalize(attribute)
normalized_attribute and normalized_attribute != "objectClass"
end
private
def entry_attribute
@entry_attribute ||=
connection.entry_attribute(classes.collect(&:name))
end
end
included do
alias_method :new_record?, :new_entry?
class << self
unless method_defined?(:human_attribute_name_with_gettext)
def human_attribute_name_with_gettext(attribute_key_name, options={})
logger.warn("options was ignored.") unless options.empty?
s_("#{self}|#{attribute_key_name.to_s.humanize}")
end
end
end
class_local_attr_accessor true, :validation_skip_attributes
remove_method :validation_skip_attributes
self.validation_skip_attributes = []
validate :validate_duplicated_dn_creation, :on => :create
validate :validate_duplicated_dn_rename, :on => :update
validate :validate_dn
validate :validate_excluded_classes
validate :validate_required_ldap_values
validate :validate_ldap_values
end
def validation_skip_attributes
@validation_skip_attributes ||= []
end
def validation_skip_attributes=(attributes)
@validation_skip_attributes = attributes
end
def valid?(context = nil)
context ||= (new_entry? ? :create : :update)
output = super(context)
errors.empty? && output
end
def save(**options)
perform_validations(options) ? super : false
end
def save!(**options)
perform_validations(options) ? super : raise(EntryInvalid.new(self))
end
private
def perform_validations(options)
if options[:validate] == false
true
else
valid?(options[:context])
end
end
def format_validation_message(format, parameters)
format % parameters
end
def validate_duplicated_dn_creation
_dn = nil
begin
_dn = dn
rescue DistinguishedNameInvalid, DistinguishedNameNotSetError
return
end
if _dn and exist?
format = _("is duplicated: %s")
message = format_validation_message(format, _dn)
errors.add("distinguishedName", message)
end
end
def validate_duplicated_dn_rename
_dn_attribute = dn_attribute_with_fallback
original_dn_value = @ldap_data[_dn_attribute]
current_dn_value = @data[_dn_attribute]
return if original_dn_value == current_dn_value
return if original_dn_value == [current_dn_value]
_dn = nil
begin
_dn = dn
rescue DistinguishedNameInvalid, DistinguishedNameNotSetError
return
end
if _dn and exist?
format = _("is duplicated: %s")
message = format_validation_message(format, _dn)
errors.add("distinguishedName", message)
end
end
def validate_dn
dn
rescue DistinguishedNameInvalid
format = _("is invalid: %s")
message = format_validation_message(format, $!.message)
errors.add("distinguishedName", message)
rescue DistinguishedNameNotSetError
format = _("isn't set: %s")
message = format_validation_message(format, $!.message)
errors.add("distinguishedName", message)
end
def validate_excluded_classes
excluded_classes = self.class.excluded_classes
return if excluded_classes.empty?
_schema = schema
_classes = classes.collect do |name|
_schema.object_class(name)
end
unexpected_classes = excluded_classes.inject([]) do |classes, name|
excluded_class = _schema.object_class(name)
if _classes.include?(excluded_class)
classes << excluded_class
end
classes
end
return if unexpected_classes.empty?
names = unexpected_classes.collect do |object_class|
self.class.human_object_class_name(object_class)
end
format = n_("has excluded value: %s",
"has excluded values: %s",
names.size)
message = format_validation_message(format, names.join(", "))
errors.add("objectClass", message)
end
# validate_required_ldap_values
#
# Basic validation:
# - Verify that every 'MUST' specified in the schema has a value defined
def validate_required_ldap_values
_schema = nil
@validation_skip_attributes ||= []
_validation_skip_attributes =
@validation_skip_attributes +
(self.class.validation_skip_attributes || [])
# Make sure all MUST attributes have a value
entry_attribute.object_classes.each do |object_class|
object_class.must.each do |required_attribute|
# Normalize to ensure we catch schema problems
# needed?
real_name = to_real_attribute_name(required_attribute.name, true)
raise UnknownAttribute.new(required_attribute) if real_name.nil?
next if required_attribute.read_only?
next if _validation_skip_attributes.include?(real_name)
value = @data[real_name]
next unless self.class.blank_value?(value)
_schema ||= schema
aliases = required_attribute.aliases.collect do |name|
self.class.human_attribute_name(name)
end
args = [self.class.human_object_class_name(object_class)]
if aliases.empty?
format = _("is required attribute by objectClass '%s'")
else
format = _("is required attribute by objectClass " \
"'%s': aliases: %s")
args << aliases.join(', ')
end
message = format_validation_message(format, args)
errors.add(real_name, message)
end
end
end
def validate_ldap_values
entry_attribute.schemata.each do |name, attribute|
value = self[name]
# Is it really proper location for setting encoding?
attribute.apply_encoding(value)
next if self.class.blank_value?(value)
validate_ldap_value(attribute, name, value)
end
end
def validate_ldap_value(attribute, name, value)
failed_reason, option = attribute.validate(value)
return if failed_reason.nil?
if attribute.binary?
inspected_value = _("<binary-value>")
else
inspected_value = self.class.human_readable_format(value)
end
params = [inspected_value,
self.class.human_syntax_description(attribute.syntax),
failed_reason]
if option
format = _("(%s) has invalid format: %s: required syntax: %s: %s")
else
format = _("has invalid format: %s: required syntax: %s: %s")
end
params.unshift(option) if option
message = format_validation_message(format, params)
errors.add(name, message)
end
end
end
|