scimitar 2.8.0 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +23 -18
- data/app/controllers/scimitar/application_controller.rb +4 -5
- data/app/controllers/scimitar/resource_types_controller.rb +7 -1
- data/app/controllers/scimitar/schemas_controller.rb +361 -1
- data/app/models/scimitar/engine_configuration.rb +3 -1
- data/app/models/scimitar/lists/query_parser.rb +10 -10
- data/app/models/scimitar/resource_type.rb +4 -6
- data/app/models/scimitar/resources/base.rb +37 -6
- data/app/models/scimitar/resources/mixin.rb +15 -10
- data/app/models/scimitar/schema/base.rb +1 -1
- data/config/initializers/scimitar.rb +41 -0
- data/lib/scimitar/engine.rb +50 -12
- data/lib/scimitar/support/utilities.rb +8 -3
- data/lib/scimitar/version.rb +2 -2
- data/spec/apps/dummy/app/models/mock_user.rb +11 -3
- data/spec/apps/dummy/config/initializers/scimitar.rb +29 -1
- data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -0
- data/spec/apps/dummy/db/schema.rb +1 -0
- data/spec/controllers/scimitar/resource_types_controller_spec.rb +8 -4
- data/spec/controllers/scimitar/schemas_controller_spec.rb +342 -54
- data/spec/models/scimitar/lists/query_parser_spec.rb +5 -0
- data/spec/models/scimitar/resources/base_spec.rb +11 -11
- data/spec/models/scimitar/resources/base_validation_spec.rb +1 -1
- data/spec/models/scimitar/resources/mixin_spec.rb +31 -12
- data/spec/requests/active_record_backed_resources_controller_spec.rb +86 -2
- data/spec/requests/engine_spec.rb +75 -0
- data/spec/spec_helper.rb +1 -1
- metadata +21 -21
@@ -35,14 +35,45 @@ module Scimitar
|
|
35
35
|
@errors = ActiveModel::Errors.new(self)
|
36
36
|
end
|
37
37
|
|
38
|
+
# Scimitar has at present a general limitation in handling schema IDs,
|
39
|
+
# which just involves stripping them and requiring attributes across all
|
40
|
+
# extension schemas to be overall unique.
|
41
|
+
#
|
42
|
+
# This method takes an options payload for the initializer and strips out
|
43
|
+
# *recognised* schema IDs, so that the resulting attribute data matches
|
44
|
+
# the resource attribute map.
|
45
|
+
#
|
46
|
+
# +attributes+:: Attributes to assign via initializer; typically a POST
|
47
|
+
# payload of attributes that has been run through Rails
|
48
|
+
# strong parameters for safety.
|
49
|
+
#
|
50
|
+
# Returns a new object of the same class as +options+ with recognised
|
51
|
+
# schema IDs removed.
|
52
|
+
#
|
38
53
|
def flatten_extension_attributes(options)
|
39
|
-
flattened
|
40
|
-
self.class.extended_schemas.
|
41
|
-
|
42
|
-
|
54
|
+
flattened = options.class.new
|
55
|
+
lower_case_schema_ids = self.class.extended_schemas.map do | schema |
|
56
|
+
schema.id.downcase()
|
57
|
+
end
|
58
|
+
|
59
|
+
options.each do | key, value |
|
60
|
+
path = Scimitar::Support::Utilities::path_str_to_array(
|
61
|
+
self.class.extended_schemas,
|
62
|
+
key
|
63
|
+
)
|
64
|
+
|
65
|
+
if path.first.include?(':') && lower_case_schema_ids.include?(path.first.downcase)
|
66
|
+
path.shift()
|
67
|
+
end
|
68
|
+
|
69
|
+
if path.empty?
|
70
|
+
flattened.merge!(value)
|
71
|
+
else
|
72
|
+
flattened[path.join('.')] = value
|
43
73
|
end
|
44
74
|
end
|
45
|
-
|
75
|
+
|
76
|
+
return flattened
|
46
77
|
end
|
47
78
|
|
48
79
|
# Can be used to extend an existing resource type's schema. For example:
|
@@ -127,7 +158,7 @@ module Scimitar
|
|
127
158
|
hash.with_indifferent_access.each_pair do |attr_name, attr_value|
|
128
159
|
scim_attribute = self.class.complex_scim_attributes[attr_name].try(:first)
|
129
160
|
|
130
|
-
if scim_attribute
|
161
|
+
if scim_attribute&.complexType
|
131
162
|
if scim_attribute.multiValued
|
132
163
|
self.send("#{attr_name}=", attr_value&.map {|attr_for_each_item| complex_type_from_hash(scim_attribute, attr_for_each_item)})
|
133
164
|
else
|
@@ -139,11 +139,12 @@ module Scimitar
|
|
139
139
|
# # ...
|
140
140
|
# groups: [
|
141
141
|
# {
|
142
|
-
# list:
|
142
|
+
# list: :users, # <-- i.e. Team.users,
|
143
143
|
# using: {
|
144
144
|
# value: :id, # <-- i.e. Team.users[n].id
|
145
145
|
# display: :full_name # <-- i.e. Team.users[n].full_name
|
146
146
|
# },
|
147
|
+
# class: Team, # Optional; see below
|
147
148
|
# find_with: -> (scim_list_entry) {...} # See below
|
148
149
|
# }
|
149
150
|
# ],
|
@@ -159,7 +160,10 @@ module Scimitar
|
|
159
160
|
# example above, "find_with"'s Proc might look at a SCIM entry value which
|
160
161
|
# is expected to be a user ID and find that User. The mapped set of User
|
161
162
|
# data thus found would be written back with "#users=", due to the ":list"
|
162
|
-
# key declaring the method name ":users".
|
163
|
+
# key declaring the method name ":users". The optional "class" key is
|
164
|
+
# recommended but not really *needed* unless the configuration option
|
165
|
+
# Scimitar::EngineConfiguration::schema_list_from_attribute_mappings is
|
166
|
+
# defined; see documentation of that option for more information.
|
163
167
|
#
|
164
168
|
# Note that you can only use either:
|
165
169
|
#
|
@@ -176,7 +180,8 @@ module Scimitar
|
|
176
180
|
# == scim_mutable_attributes
|
177
181
|
#
|
178
182
|
# Define this method to return a Set (preferred) or Array of names of
|
179
|
-
# attributes which may be written in the mixing-in class.
|
183
|
+
# attributes which may be written in the mixing-in class. The names MUST be
|
184
|
+
# expressed as Symbols, *not* Strings.
|
180
185
|
#
|
181
186
|
# If you return +nil+, it is assumed that +any+ attribute mapped by
|
182
187
|
# ::scim_attributes_map which has a write accessor will be eligible for
|
@@ -291,7 +296,7 @@ module Scimitar
|
|
291
296
|
# the result in an instance variable.
|
292
297
|
#
|
293
298
|
def scim_mutable_attributes
|
294
|
-
@scim_mutable_attributes ||= self.class.scim_mutable_attributes()
|
299
|
+
@scim_mutable_attributes ||= self.class.scim_mutable_attributes()&.map(&:to_sym)
|
295
300
|
|
296
301
|
if @scim_mutable_attributes.nil?
|
297
302
|
@scim_mutable_attributes = Set.new
|
@@ -468,7 +473,7 @@ module Scimitar
|
|
468
473
|
path_str = operation['path' ]
|
469
474
|
value = operation['value']
|
470
475
|
|
471
|
-
unless [
|
476
|
+
unless %w[add remove replace].include?(nature)
|
472
477
|
raise Scimitar::InvalidSyntaxError.new("Unrecognised PATCH \"op\" value of \"#{nature}\"")
|
473
478
|
end
|
474
479
|
|
@@ -608,7 +613,7 @@ module Scimitar
|
|
608
613
|
built_dynamic_list = false
|
609
614
|
mapped_array = attrs_map_or_leaf_value.map do |value|
|
610
615
|
if ! value.is_a?(Hash)
|
611
|
-
raise 'Bad attribute map: Array contains
|
616
|
+
raise 'Bad attribute map: Array contains something other than mapping Hash(es)'
|
612
617
|
|
613
618
|
elsif value.key?(:match) # Static map
|
614
619
|
static_hash = { value[:match] => value[:with] }
|
@@ -736,7 +741,7 @@ module Scimitar
|
|
736
741
|
# +path+:: Array of SCIM attribute names giving a
|
737
742
|
# path into the SCIM schema where
|
738
743
|
# iteration has reached. Used to find the
|
739
|
-
# schema attribute
|
744
|
+
# schema attribute definition and check
|
740
745
|
# mutability before writing.
|
741
746
|
#
|
742
747
|
def from_scim_backend!(
|
@@ -1083,7 +1088,7 @@ module Scimitar
|
|
1083
1088
|
# associated collection or clearing a local model attribute
|
1084
1089
|
# directly to "nil").
|
1085
1090
|
#
|
1086
|
-
|
1091
|
+
unless handled
|
1087
1092
|
current_data_at_path[matched_index] = nil
|
1088
1093
|
compact_after = true
|
1089
1094
|
end
|
@@ -1285,7 +1290,7 @@ module Scimitar
|
|
1285
1290
|
end
|
1286
1291
|
end
|
1287
1292
|
|
1288
|
-
|
1293
|
+
unless handled
|
1289
1294
|
altering_hash[path_component] = []
|
1290
1295
|
end
|
1291
1296
|
|
@@ -1440,7 +1445,7 @@ module Scimitar
|
|
1440
1445
|
# { value: :work_email }
|
1441
1446
|
#
|
1442
1447
|
# If there was a SCIM entry with a type of something unrecognised,
|
1443
|
-
# such as '
|
1448
|
+
# such as 'holiday', then +nil+ would be returned since there is no
|
1444
1449
|
# matching attribute map entry.
|
1445
1450
|
#
|
1446
1451
|
# Note that the <tt>:with_attr_map</tt> array can contain dynamic
|
@@ -36,7 +36,7 @@ module Scimitar
|
|
36
36
|
scim_attributes.map { |scim_attribute| scim_attribute.clone }
|
37
37
|
end
|
38
38
|
|
39
|
-
# Find a given attribute this schema, travelling down a path to any
|
39
|
+
# Find a given attribute of this schema, travelling down a path to any
|
40
40
|
# sub-attributes within. Given that callers might be dealing with paths
|
41
41
|
# into actual SCIM data, array indices for multi-value attributes are
|
42
42
|
# allowed (as integers) and simply skipped - only the names are of
|
@@ -106,6 +106,47 @@ Rails.application.config.to_prepare do # (required for >= Rails 7 / Zeitwerk)
|
|
106
106
|
# whatever that means for you receiving system in your model code.
|
107
107
|
#
|
108
108
|
# optional_value_fields_required: false
|
109
|
+
|
110
|
+
# The SCIM standard `/Schemas` endpoint lists, by default, all known schema
|
111
|
+
# definitions with the mutabilty (read-write, read-only, write-only) state
|
112
|
+
# described by those definitions, and includes all defined attributes. For
|
113
|
+
# user-defined schema, this will typically exactly match your underlying
|
114
|
+
# mapped attribute and model capability - it wouldn't make sense to define
|
115
|
+
# your own schema that misrepresented the implementation! For core SCIM RFC
|
116
|
+
# schema, though, you might want to only list actually mapped attributes.
|
117
|
+
# Further, if you happen to have a non-compliant implementation especially
|
118
|
+
# in relation to mutability of some attributes, you may want to report that
|
119
|
+
# accurately in the '/Schemas' list, for auto-discovery purposes. To switch
|
120
|
+
# to a significantly slower but more accurate render method for the list,
|
121
|
+
# driven by your resource subclasses and their attribute maps, set:
|
122
|
+
#
|
123
|
+
# schema_list_from_attribute_mappings: [...array...]
|
124
|
+
#
|
125
|
+
# ...where you provide an Array of *models*, your classes that include the
|
126
|
+
# Scimitar::Resources::Mixin module and, therefore, define an attribute map
|
127
|
+
# translating SCIM schema attributes into actual implemented data. These
|
128
|
+
# must *uniquely* describe, via the Scimitar resources they each declare in
|
129
|
+
# their Scimitar::Resources::Mixin::scim_resource_type implementation, the
|
130
|
+
# set of schemas and extended schemas you want to render. Should resources
|
131
|
+
# share schema, the '/Schemas' endpoint will fail since it cannot determine
|
132
|
+
# which model attribute map it should use and it needs the map in order to
|
133
|
+
# resolve the differences (if any) between what the schema might say, and
|
134
|
+
# what the actual underlying model supports.
|
135
|
+
#
|
136
|
+
# It is further _very_ _strongly_ _recommended_ that, for any
|
137
|
+
# +scim_attributes_map+ containing a collection which has "list:" key (for
|
138
|
+
# an associative array of zero or more entities; the Groups to which a User
|
139
|
+
# might belong is a good example) then you should also specify the "class:"
|
140
|
+
# key, giving the class used for objects in that associated collection. The
|
141
|
+
# class *must* include Scimitar::Resources::Mixin, since its own attribute
|
142
|
+
# map is consulted in order to render the part of the schema describing
|
143
|
+
# those associated properties in the owning resource. If you don't do this,
|
144
|
+
# and if you're using ActiveRecord, then Scimitar attempts association
|
145
|
+
# reflection to determine the collection class - but that's more fragile
|
146
|
+
# than just being told the exact class in the attribute map. No matter how
|
147
|
+
# this class is determined, though, it must be possible to create a simple
|
148
|
+
# instance with +new+ and no parameters, since that's needed in order to
|
149
|
+
# call Scimitar::Resources::Mixin#scim_mutable_attributes.
|
109
150
|
})
|
110
151
|
|
111
152
|
end
|
data/lib/scimitar/engine.rb
CHANGED
@@ -15,8 +15,24 @@ module Scimitar
|
|
15
15
|
JSON.parse(body)
|
16
16
|
end
|
17
17
|
|
18
|
+
# Return an Array of all supported default and custom resource classes.
|
19
|
+
# See also :add_custom_resource and :set_default_resources.
|
20
|
+
#
|
18
21
|
def self.resources
|
19
|
-
default_resources + custom_resources
|
22
|
+
self.default_resources() + self.custom_resources()
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns a flat array of instances of all resource schema included in the
|
26
|
+
# resource classes returned by ::resources.
|
27
|
+
#
|
28
|
+
def self.schemas
|
29
|
+
self.resources().map(&:schemas).flatten.uniq.map(&:new)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the list of custom resources, if any.
|
33
|
+
#
|
34
|
+
def self.custom_resources
|
35
|
+
@custom_resources ||= []
|
20
36
|
end
|
21
37
|
|
22
38
|
# Can be used to add a new resource type which is not provided by the gem.
|
@@ -37,7 +53,7 @@ module Scimitar
|
|
37
53
|
# Scimitar::Engine.add_custom_resource Scim::Resources::ShinyResource
|
38
54
|
#
|
39
55
|
def self.add_custom_resource(resource)
|
40
|
-
custom_resources << resource
|
56
|
+
self.custom_resources() << resource
|
41
57
|
end
|
42
58
|
|
43
59
|
# Resets the resource list to default. This is really only intended for use
|
@@ -47,23 +63,45 @@ module Scimitar
|
|
47
63
|
@custom_resources = []
|
48
64
|
end
|
49
65
|
|
50
|
-
# Returns the
|
51
|
-
#
|
52
|
-
def self.custom_resources
|
53
|
-
@custom_resources ||= []
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns the default resources added in this gem:
|
66
|
+
# Returns the default resources added in this gem - by default, these are:
|
57
67
|
#
|
58
68
|
# * Scimitar::Resources::User
|
59
69
|
# * Scimitar::Resources::Group
|
60
70
|
#
|
71
|
+
# ...but if an implementation does not e.g. support Group, it can
|
72
|
+
# be overridden via ::set_default_resources to help with service
|
73
|
+
# auto-discovery.
|
74
|
+
#
|
61
75
|
def self.default_resources
|
62
|
-
[ Resources::User, Resources::Group ]
|
76
|
+
@standard_default_resources = [ Resources::User, Resources::Group ]
|
77
|
+
@default_resources ||= @standard_default_resources.dup()
|
63
78
|
end
|
64
79
|
|
65
|
-
|
66
|
-
|
80
|
+
# Override the resources returned by ::default_resources.
|
81
|
+
#
|
82
|
+
# +resource_array+:: An Array containing one or both of
|
83
|
+
# Scimitar::Resources::User and/or
|
84
|
+
# Scimitar::Resources::Group, and nothing else.
|
85
|
+
#
|
86
|
+
def self.set_default_resources(resource_array)
|
87
|
+
self.default_resources()
|
88
|
+
unrecognised_resources = resource_array - @standard_default_resources
|
89
|
+
|
90
|
+
if unrecognised_resources.any?
|
91
|
+
raise "Scimitar::Engine.set_default_resources: Only #{@standard_default_resources.map(&:name).join(', ')} are supported"
|
92
|
+
elsif resource_array.empty?
|
93
|
+
raise 'Scimitar::Engine.set_default_resources: At least one resource must be given'
|
94
|
+
end
|
95
|
+
|
96
|
+
@default_resources = resource_array
|
97
|
+
end
|
98
|
+
|
99
|
+
# Resets the default resource list. This is really only intended for use
|
100
|
+
# during testing, to avoid one test polluting another.
|
101
|
+
#
|
102
|
+
def self.reset_default_resources
|
103
|
+
self.default_resources()
|
104
|
+
@default_resources = @standard_default_resources
|
67
105
|
end
|
68
106
|
|
69
107
|
end
|
@@ -57,9 +57,10 @@ module Scimitar
|
|
57
57
|
# <tt>scim_resource_type.extended_schemas</tt> value. The
|
58
58
|
# Array should be empty if there are no extensions.
|
59
59
|
#
|
60
|
-
# +path_str+:: Path
|
60
|
+
# +path_str+:: Path String, e.g. <tt>"password"</tt>, <tt>"name.givenName"</tt>,
|
61
61
|
# <tt>"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"</tt> (special case),
|
62
62
|
# <tt>"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:organization"</tt>
|
63
|
+
# (if given a Symbol, it'll be converted to a String).
|
63
64
|
#
|
64
65
|
# Returns an array of components, e.g. <tt>["password"]</tt>, <tt>["name",
|
65
66
|
# "givenName"]</tt>,
|
@@ -74,6 +75,7 @@ module Scimitar
|
|
74
75
|
# path-free payload.
|
75
76
|
#
|
76
77
|
def self.path_str_to_array(schemas, path_str)
|
78
|
+
path_str = path_str.to_s
|
77
79
|
components = []
|
78
80
|
|
79
81
|
# Note the ":" separating the schema ID (URN) from the attribute.
|
@@ -84,11 +86,14 @@ module Scimitar
|
|
84
86
|
# particular, https://tools.ietf.org/html/rfc7644#page-35.
|
85
87
|
#
|
86
88
|
if path_str.include?(':')
|
89
|
+
lower_case_path_str = path_str.downcase()
|
90
|
+
|
87
91
|
schemas.each do |schema|
|
88
|
-
|
92
|
+
lower_case_schema_id = schema.id.downcase()
|
93
|
+
attributes_after_schema_id = lower_case_path_str.split(lower_case_schema_id + ':').drop(1)
|
89
94
|
|
90
95
|
if attributes_after_schema_id.empty?
|
91
|
-
components += [schema.id]
|
96
|
+
components += [schema.id] if lower_case_path_str == lower_case_schema_id
|
92
97
|
else
|
93
98
|
attributes_after_schema_id.each do |component|
|
94
99
|
components += [schema.id] + component.split('.')
|
data/lib/scimitar/version.rb
CHANGED
@@ -3,11 +3,11 @@ module Scimitar
|
|
3
3
|
# Gem version. If this changes, be sure to re-run "bundle install" or
|
4
4
|
# "bundle update".
|
5
5
|
#
|
6
|
-
VERSION = '2.
|
6
|
+
VERSION = '2.10.0'
|
7
7
|
|
8
8
|
# Date for VERSION. If this changes, be sure to re-run "bundle install"
|
9
9
|
# or "bundle update".
|
10
10
|
#
|
11
|
-
DATE = '2024-
|
11
|
+
DATE = '2024-10-22'
|
12
12
|
|
13
13
|
end
|
@@ -18,6 +18,7 @@ class MockUser < ActiveRecord::Base
|
|
18
18
|
work_phone_number
|
19
19
|
organization
|
20
20
|
department
|
21
|
+
manager
|
21
22
|
mock_groups
|
22
23
|
}
|
23
24
|
|
@@ -48,6 +49,7 @@ class MockUser < ActiveRecord::Base
|
|
48
49
|
externalId: :scim_uid,
|
49
50
|
userName: :username,
|
50
51
|
password: :password,
|
52
|
+
active: :is_active,
|
51
53
|
name: {
|
52
54
|
givenName: :first_name,
|
53
55
|
familyName: :last_name
|
@@ -80,8 +82,11 @@ class MockUser < ActiveRecord::Base
|
|
80
82
|
}
|
81
83
|
},
|
82
84
|
],
|
83
|
-
groups: [
|
85
|
+
groups: [
|
84
86
|
{
|
87
|
+
# Read-only, so no :find_with key. There's no 'class' specified here
|
88
|
+
# either, to help test the "/Schemas" endpoint's reflection code.
|
89
|
+
#
|
85
90
|
list: :mock_groups,
|
86
91
|
using: {
|
87
92
|
value: :id,
|
@@ -89,7 +94,6 @@ class MockUser < ActiveRecord::Base
|
|
89
94
|
}
|
90
95
|
}
|
91
96
|
],
|
92
|
-
active: :is_active,
|
93
97
|
|
94
98
|
# Custom extension schema - see configuration in
|
95
99
|
# "spec/apps/dummy/config/initializers/scimitar.rb".
|
@@ -97,6 +101,9 @@ class MockUser < ActiveRecord::Base
|
|
97
101
|
organization: :organization,
|
98
102
|
department: :department,
|
99
103
|
primaryEmail: :scim_primary_email,
|
104
|
+
|
105
|
+
manager: :manager,
|
106
|
+
|
100
107
|
userGroups: [
|
101
108
|
{
|
102
109
|
list: :mock_groups,
|
@@ -130,7 +137,8 @@ class MockUser < ActiveRecord::Base
|
|
130
137
|
}
|
131
138
|
end
|
132
139
|
|
133
|
-
# reader
|
140
|
+
# Custom attribute reader
|
141
|
+
#
|
134
142
|
def scim_primary_email
|
135
143
|
work_email_address
|
136
144
|
end
|
@@ -33,10 +33,13 @@ Rails.application.config.to_prepare do
|
|
33
33
|
|
34
34
|
module ScimSchemaExtensions
|
35
35
|
module User
|
36
|
+
|
37
|
+
# This "looks like" part of the standard Enterprise extension.
|
38
|
+
#
|
36
39
|
class Enterprise < Scimitar::Schema::Base
|
37
40
|
def initialize(options = {})
|
38
41
|
super(
|
39
|
-
name: '
|
42
|
+
name: 'EnterpriseExtendedUser',
|
40
43
|
description: 'Enterprise extension for a User',
|
41
44
|
id: self.class.id,
|
42
45
|
scim_attributes: self.class.scim_attributes
|
@@ -55,8 +58,33 @@ Rails.application.config.to_prepare do
|
|
55
58
|
]
|
56
59
|
end
|
57
60
|
end
|
61
|
+
|
62
|
+
# In https://github.com/RIPAGlobal/scimitar/issues/122 we learn that with
|
63
|
+
# more than one extension, things can go wrong - so now we test with two.
|
64
|
+
#
|
65
|
+
class Manager < Scimitar::Schema::Base
|
66
|
+
def initialize(options = {})
|
67
|
+
super(
|
68
|
+
name: 'ManagementExtendedUser',
|
69
|
+
description: 'Management extension for a User',
|
70
|
+
id: self.class.id,
|
71
|
+
scim_attributes: self.class.scim_attributes
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.id
|
76
|
+
'urn:ietf:params:scim:schemas:extension:manager:1.0:User'
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.scim_attributes
|
80
|
+
[
|
81
|
+
Scimitar::Schema::Attribute.new(name: 'manager', type: 'string')
|
82
|
+
]
|
83
|
+
end
|
84
|
+
end
|
58
85
|
end
|
59
86
|
end
|
60
87
|
|
61
88
|
Scimitar::Resources::User.extend_schema ScimSchemaExtensions::User::Enterprise
|
89
|
+
Scimitar::Resources::User.extend_schema ScimSchemaExtensions::User::Manager
|
62
90
|
end
|
@@ -9,11 +9,15 @@ RSpec.describe Scimitar::ResourceTypesController do
|
|
9
9
|
it 'renders the resource type for user' do
|
10
10
|
get :index, format: :scim
|
11
11
|
response_hash = JSON.parse(response.body)
|
12
|
-
expected_response =
|
13
|
-
|
14
|
-
|
12
|
+
expected_response = {
|
13
|
+
schemas: ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],
|
14
|
+
totalResults: 2,
|
15
|
+
Resources: [
|
16
|
+
Scimitar::Resources::User.resource_type(scim_resource_type_url(name: 'User', test: 1)),
|
17
|
+
Scimitar::Resources::Group.resource_type(scim_resource_type_url(name: 'Group', test: 1))
|
18
|
+
]
|
19
|
+
}.to_json
|
15
20
|
|
16
|
-
response_hash = JSON.parse(response.body)
|
17
21
|
expect(response_hash).to eql(JSON.parse(expected_response))
|
18
22
|
end
|
19
23
|
|