Commit 79620de
Changed files (3)
lib
scim
kit
spec
scim
kit
lib/scim/kit/v2/attribute.rb
@@ -13,6 +13,7 @@ module Scim
validate :presence_of_value, if: proc { |x| x.type.required }
validate :inclusion_of_value, if: proc { |x| x.type.canonical_values }
+ validate :validate_array, if: proc { |x| x.type.multi_valued }
def initialize(type:, value: nil)
@type = type
@@ -37,6 +38,12 @@ module Scim
errors.add(type.name, I18n.t('errors.messages.inclusion'))
end
+
+ def validate_array
+ return if _value.respond_to?(:each) && _value.all? { |x| type.valid?(x) }
+
+ errors.add(type.name, I18n.t('errors.messages.invalid'))
+ end
end
end
end
lib/scim/kit/v2/attribute_type.rb
@@ -6,6 +6,7 @@ module Scim
# Represents a scim Attribute type
class AttributeType
include Templatable
+ BASE64_FORMAT = %r(\A([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\Z).freeze
DATATYPES = {
string: 'string',
boolean: 'boolean',
@@ -23,6 +24,13 @@ module Scim
datetime: ->(x) { x.is_a?(::String) ? DateTime.parse(x) : x },
binary: ->(x) { Base64.strict_encode64(x) }
}.freeze
+ VALIDATIONS = {
+ string: ->(x) { x.is_a?(String) },
+ decimal: ->(x) { x.is_a?(Float) },
+ integer: ->(x) { x&.integer? },
+ datetime: ->(x) { x.is_a?(DateTime) },
+ binary: ->(x) { x.is_a?(String) && !!x.match(BASE64_FORMAT) }
+ }
attr_accessor :canonical_values
attr_accessor :case_exact
attr_accessor :description
@@ -89,6 +97,10 @@ module Scim
coercion ? coercion.call(value) : value
end
+ def valid?(value)
+ VALIDATIONS[type]&.call(value)
+ end
+
private
def string?
spec/scim/kit/v2/attribute_spec.rb
@@ -13,6 +13,7 @@ RSpec.describe Scim::Kit::V2::Attribute do
specify { expect(subject._value).to eql(user_name) }
specify { expect(subject.as_json[:userName]).to eql(user_name) }
+ specify { expect(subject).to be_valid }
end
context 'when multiple values are allowed' do
@@ -22,6 +23,28 @@ RSpec.describe Scim::Kit::V2::Attribute do
end
specify { expect(subject._value).to match_array(%w[superman batman]) }
+
+ context "when a single value is provided" do
+ before do
+ type.multi_valued = true
+ subject._value = 'batman'
+ subject.valid?
+ end
+
+ specify { expect(subject).not_to be_valid }
+ specify { expect(subject.errors[:user_name]).to be_present }
+ end
+
+ context "when the wrong type is used" do
+ before do
+ type.multi_valued = true
+ subject._value = [1.0, 2.0]
+ subject.valid?
+ end
+
+ specify { expect(subject).not_to be_valid }
+ specify { expect(subject.errors[:user_name]).to be_present }
+ end
end
context 'when integer' do