main
 1# frozen_string_literal: true
 2
 3require 'scim/kit/v2/attributable'
 4require 'scim/kit/v2/attribute'
 5require 'scim/kit/v2/attribute_type'
 6require 'scim/kit/v2/authentication_scheme'
 7require 'scim/kit/v2/complex_attribute_validator'
 8require 'scim/kit/v2/configuration'
 9require 'scim/kit/v2/messages'
10require 'scim/kit/v2/meta'
11require 'scim/kit/v2/mutability'
12require 'scim/kit/v2/resource'
13require 'scim/kit/v2/error'
14require 'scim/kit/v2/filter'
15require 'scim/kit/v2/filter/node'
16require 'scim/kit/v2/filter/visitor'
17require 'scim/kit/v2/resource_type'
18require 'scim/kit/v2/returned'
19require 'scim/kit/v2/schema'
20require 'scim/kit/v2/schemas'
21require 'scim/kit/v2/service_provider_configuration'
22require 'scim/kit/v2/supportable'
23require 'scim/kit/v2/uniqueness'
24require 'scim/kit/v2/unknown_attribute'
25
26module Scim
27  module Kit
28    # Version 2 of the SCIM RFC https://tools.ietf.org/html/rfc7644
29    module V2
30      BASE64 = %r(
31        \A([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\Z
32      )x
33      BOOLEAN_VALUES = [true, false].freeze
34      DATATYPES = {
35        string: 'string',
36        boolean: 'boolean',
37        decimal: 'decimal',
38        integer: 'integer',
39        datetime: 'dateTime',
40        binary: 'binary',
41        reference: 'reference',
42        complex: 'complex'
43      }.freeze
44      COERCION = {
45        binary: lambda { |x|
46          VALIDATIONS[:binary].call(x) ? x : Base64.strict_encode64(x)
47        },
48        boolean: lambda { |x|
49          return true if x == 'true'
50          return false if x == 'false'
51
52          x
53        },
54        datetime: ->(x) { x.is_a?(::String) ? DateTime.parse(x) : x },
55        decimal: ->(x) { x.to_f },
56        integer: ->(x) { x.to_i },
57        string: ->(x) { x.to_s }
58      }.freeze
59      VALIDATIONS = {
60        binary: ->(x) { x.is_a?(String) && x.match?(BASE64) },
61        boolean: ->(x) { BOOLEAN_VALUES.include?(x) },
62        datetime: ->(x) { x.is_a?(DateTime) },
63        decimal: ->(x) { x.is_a?(Float) },
64        integer: lambda { |x|
65          begin
66            x&.integer?
67          rescue StandardError
68            false
69          end
70        },
71        reference: ->(x) { x&.to_s =~ /\A#{URI::DEFAULT_PARSER.make_regexp(%w[http https])}\z/ },
72        string: ->(x) { x.is_a?(String) }
73      }.freeze
74
75      class << self
76        def configuration
77          @configuration ||= ::Scim::Kit::V2::Configuration.new
78        end
79
80        def configure
81          yield ::Scim::Kit::V2::Configuration::Builder.new(configuration)
82        end
83      end
84    end
85  end
86end