scimitar 2.8.0 → 2.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|