Skip to content

Commit 96673f0

Browse files
committed
Feature-complete with decent tests
1 parent 93a4aa5 commit 96673f0

File tree

8 files changed

+573
-167
lines changed

8 files changed

+573
-167
lines changed

app/controllers/scimitar/schemas_controller.rb

+176-81
Large diffs are not rendered by default.

app/models/scimitar/engine_configuration.rb

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class EngineConfiguration
1414
:application_controller_mixin,
1515
:exception_reporter,
1616
:optional_value_fields_required,
17+
:schema_list_from_attribute_mappings,
1718
)
1819

1920
def initialize(attributes = {})
@@ -22,7 +23,8 @@ def initialize(attributes = {})
2223
# Set defaults that may be overridden by the initializer.
2324
#
2425
defaults = {
25-
optional_value_fields_required: true
26+
optional_value_fields_required: true,
27+
schema_list_from_attribute_mappings: []
2628
}
2729

2830
super(defaults.merge(attributes))

app/models/scimitar/resources/mixin.rb

+9-4
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,12 @@ module Resources
139139
# # ...
140140
# groups: [
141141
# {
142-
# list: :users, # <-- i.e. Team.users,
142+
# list: :users, # <-- i.e. Team.users,
143143
# using: {
144144
# value: :id, # <-- i.e. Team.users[n].id
145145
# display: :full_name # <-- i.e. Team.users[n].full_name
146146
# },
147+
# class: Team, # Optional; see below
147148
# find_with: -> (scim_list_entry) {...} # See below
148149
# }
149150
# ],
@@ -159,7 +160,10 @@ module Resources
159160
# example above, "find_with"'s Proc might look at a SCIM entry value which
160161
# is expected to be a user ID and find that User. The mapped set of User
161162
# 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.
163167
#
164168
# Note that you can only use either:
165169
#
@@ -176,7 +180,8 @@ module Resources
176180
# == scim_mutable_attributes
177181
#
178182
# 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.
180185
#
181186
# If you return +nil+, it is assumed that +any+ attribute mapped by
182187
# ::scim_attributes_map which has a write accessor will be eligible for
@@ -291,7 +296,7 @@ module Mixin
291296
# the result in an instance variable.
292297
#
293298
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)
295300

296301
if @scim_mutable_attributes.nil?
297302
@scim_mutable_attributes = Set.new

config/initializers/scimitar.rb

+41
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,47 @@
106106
# whatever that means for you receiving system in your model code.
107107
#
108108
# 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.
109150
})
110151

111152
end

0 commit comments

Comments
 (0)