scimitar 1.10.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/scimitar/active_record_backed_resources_controller.rb +23 -98
- data/app/controllers/scimitar/application_controller.rb +13 -41
- data/app/controllers/scimitar/resource_types_controller.rb +2 -0
- data/app/controllers/scimitar/resources_controller.rb +2 -0
- data/app/controllers/scimitar/schemas_controller.rb +3 -366
- data/app/controllers/scimitar/service_provider_configurations_controller.rb +1 -0
- data/app/models/scimitar/complex_types/address.rb +6 -0
- data/app/models/scimitar/engine_configuration.rb +5 -15
- data/app/models/scimitar/error_response.rb +0 -12
- data/app/models/scimitar/lists/query_parser.rb +13 -113
- data/app/models/scimitar/resource_invalid_error.rb +1 -1
- data/app/models/scimitar/resources/base.rb +9 -53
- data/app/models/scimitar/resources/mixin.rb +59 -646
- data/app/models/scimitar/schema/address.rb +0 -1
- data/app/models/scimitar/schema/attribute.rb +5 -14
- data/app/models/scimitar/schema/base.rb +1 -1
- data/app/models/scimitar/schema/name.rb +2 -2
- data/app/models/scimitar/schema/user.rb +10 -10
- data/app/models/scimitar/schema/vdtp.rb +1 -1
- data/app/models/scimitar/service_provider_configuration.rb +3 -14
- data/config/initializers/scimitar.rb +3 -69
- data/lib/scimitar/engine.rb +12 -57
- data/lib/scimitar/support/hash_with_indifferent_case_insensitive_access.rb +10 -140
- data/lib/scimitar/version.rb +2 -2
- data/lib/scimitar.rb +2 -7
- data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
- data/spec/apps/dummy/app/models/mock_group.rb +1 -1
- data/spec/apps/dummy/app/models/mock_user.rb +9 -52
- data/spec/apps/dummy/config/application.rb +1 -0
- data/spec/apps/dummy/config/environments/test.rb +28 -5
- data/spec/apps/dummy/config/initializers/scimitar.rb +10 -90
- data/spec/apps/dummy/config/routes.rb +7 -28
- data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -11
- data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
- data/spec/apps/dummy/db/schema.rb +4 -12
- data/spec/controllers/scimitar/application_controller_spec.rb +3 -126
- data/spec/controllers/scimitar/resource_types_controller_spec.rb +2 -2
- data/spec/controllers/scimitar/schemas_controller_spec.rb +48 -344
- data/spec/models/scimitar/complex_types/address_spec.rb +4 -3
- data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
- data/spec/models/scimitar/lists/query_parser_spec.rb +9 -146
- data/spec/models/scimitar/resources/base_spec.rb +71 -217
- data/spec/models/scimitar/resources/base_validation_spec.rb +5 -43
- data/spec/models/scimitar/resources/mixin_spec.rb +129 -1508
- data/spec/models/scimitar/schema/attribute_spec.rb +3 -22
- data/spec/models/scimitar/schema/base_spec.rb +1 -1
- data/spec/models/scimitar/schema/user_spec.rb +2 -12
- data/spec/requests/active_record_backed_resources_controller_spec.rb +66 -1016
- data/spec/requests/application_controller_spec.rb +3 -16
- data/spec/requests/engine_spec.rb +0 -75
- data/spec/spec_helper.rb +1 -9
- data/spec/support/hash_with_indifferent_case_insensitive_access_spec.rb +0 -108
- metadata +26 -37
- data/LICENSE.txt +0 -21
- data/README.md +0 -717
- data/lib/scimitar/support/utilities.rb +0 -111
- data/spec/apps/dummy/app/controllers/custom_create_mock_users_controller.rb +0 -25
- data/spec/apps/dummy/app/controllers/custom_replace_mock_users_controller.rb +0 -25
- data/spec/apps/dummy/app/controllers/custom_save_mock_users_controller.rb +0 -24
- data/spec/apps/dummy/app/controllers/custom_update_mock_users_controller.rb +0 -25
@@ -1,111 +0,0 @@
|
|
1
|
-
module Scimitar
|
2
|
-
|
3
|
-
# Namespace containing various chunks of Scimitar support code that don't
|
4
|
-
# logically fit into other areas.
|
5
|
-
#
|
6
|
-
module Support
|
7
|
-
|
8
|
-
# A namespace that contains various stand-alone utility methods which act
|
9
|
-
# as helpers for other parts of the code base, without risking namespace
|
10
|
-
# pollution by e.g. being part of a module loaded into a client class.
|
11
|
-
#
|
12
|
-
module Utilities
|
13
|
-
|
14
|
-
# Takes an array of components that usually come from a dotted path such
|
15
|
-
# as <tt>foo.bar.baz</tt>, along with a value that is found at the end of
|
16
|
-
# that path, then converts it into a nested Hash with each level of the
|
17
|
-
# Hash corresponding to a step along the path.
|
18
|
-
#
|
19
|
-
# This was written to help with edge case SCIM uses where (most often, at
|
20
|
-
# least) inbound calls use a dotted notation where nested values are more
|
21
|
-
# commonly accepted; converting to nesting makes it easier for subsequent
|
22
|
-
# processing code, which needs only handle nested Hash data.
|
23
|
-
#
|
24
|
-
# As an example, passing:
|
25
|
-
#
|
26
|
-
# ['foo', 'bar', 'baz'], 'value'
|
27
|
-
#
|
28
|
-
# ...yields:
|
29
|
-
#
|
30
|
-
# {'foo' => {'bar' => {'baz' => 'value'}}}
|
31
|
-
#
|
32
|
-
# Parameters:
|
33
|
-
#
|
34
|
-
# +array+:: Array containing path components, usually acquired from a
|
35
|
-
# string with dot separators and a call to String#split.
|
36
|
-
#
|
37
|
-
# +value+:: The value found at the path indicated by +array+.
|
38
|
-
#
|
39
|
-
# If +array+ is empty, +value+ is returned directly, with no nesting
|
40
|
-
# Hash wrapping it.
|
41
|
-
#
|
42
|
-
def self.dot_path(array, value)
|
43
|
-
return value if array.empty?
|
44
|
-
|
45
|
-
{}.tap do | hash |
|
46
|
-
hash[array.shift()] = self.dot_path(array, value)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Schema ID-aware splitter handling ":" or "." separators. Adapted from
|
51
|
-
# contribution by @bettysteger and @MorrisFreeman in:
|
52
|
-
#
|
53
|
-
# https://github.com/RIPAGlobal/scimitar/issues/48
|
54
|
-
# https://github.com/RIPAGlobal/scimitar/pull/49
|
55
|
-
#
|
56
|
-
# +schemas:: Array of extension schemas, e.g. a SCIM resource class'
|
57
|
-
# <tt>scim_resource_type.extended_schemas</tt> value. The
|
58
|
-
# Array should be empty if there are no extensions.
|
59
|
-
#
|
60
|
-
# +path_str+:: Path String, e.g. <tt>"password"</tt>, <tt>"name.givenName"</tt>,
|
61
|
-
# <tt>"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"</tt> (special case),
|
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).
|
64
|
-
#
|
65
|
-
# Returns an array of components, e.g. <tt>["password"]</tt>, <tt>["name",
|
66
|
-
# "givenName"]</tt>,
|
67
|
-
# <tt>["urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"]</tt> (special case),
|
68
|
-
# <tt>["urn:ietf:params:scim:schemas:extension:enterprise:2.0:User", "organization"]</tt>.
|
69
|
-
#
|
70
|
-
# The called-out special case is for a schema ID without any appended
|
71
|
-
# path components, which is returned as a single element ID to aid in
|
72
|
-
# traversal particularly of things like PATCH requests. There, a "value"
|
73
|
-
# attribute might have a key string that's simply a schema ID, with an
|
74
|
-
# object beneath that's got attribute-name pairs, possibly nested, in a
|
75
|
-
# path-free payload.
|
76
|
-
#
|
77
|
-
def self.path_str_to_array(schemas, path_str)
|
78
|
-
path_str = path_str.to_s
|
79
|
-
components = []
|
80
|
-
|
81
|
-
# Note the ":" separating the schema ID (URN) from the attribute.
|
82
|
-
# The nature of JSON rendering / other payloads might lead you to
|
83
|
-
# expect a "." as with any complex types, but that's not the case;
|
84
|
-
# see https://tools.ietf.org/html/rfc7644#section-3.10, or
|
85
|
-
# https://tools.ietf.org/html/rfc7644#section-3.5.2 of which in
|
86
|
-
# particular, https://tools.ietf.org/html/rfc7644#page-35.
|
87
|
-
#
|
88
|
-
if path_str.include?(':')
|
89
|
-
lower_case_path_str = path_str.downcase()
|
90
|
-
|
91
|
-
schemas.each do |schema|
|
92
|
-
lower_case_schema_id = schema.id.downcase()
|
93
|
-
attributes_after_schema_id = lower_case_path_str.split(lower_case_schema_id + ':').drop(1)
|
94
|
-
|
95
|
-
if attributes_after_schema_id.empty?
|
96
|
-
components += [schema.id] if lower_case_path_str == lower_case_schema_id
|
97
|
-
else
|
98
|
-
attributes_after_schema_id.each do |component|
|
99
|
-
components += [schema.id] + component.split('.')
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
components = path_str.split('.') if components.empty?
|
106
|
-
return components
|
107
|
-
end
|
108
|
-
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# For tests only - uses custom 'create' implementation which passes a block to
|
2
|
-
# Scimitar::ActiveRecordBackedResourcesController#create.
|
3
|
-
#
|
4
|
-
class CustomCreateMockUsersController < Scimitar::ActiveRecordBackedResourcesController
|
5
|
-
|
6
|
-
OVERRIDDEN_NAME = SecureRandom.uuid
|
7
|
-
|
8
|
-
def create
|
9
|
-
super do | resource |
|
10
|
-
resource.first_name = OVERRIDDEN_NAME
|
11
|
-
resource.save!
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def storage_class
|
18
|
-
MockUser
|
19
|
-
end
|
20
|
-
|
21
|
-
def storage_scope
|
22
|
-
MockUser.all
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# For tests only - uses custom 'replace' implementation which passes a block to
|
2
|
-
# Scimitar::ActiveRecordBackedResourcesController#create.
|
3
|
-
#
|
4
|
-
class CustomReplaceMockUsersController < Scimitar::ActiveRecordBackedResourcesController
|
5
|
-
|
6
|
-
OVERRIDDEN_NAME = SecureRandom.uuid
|
7
|
-
|
8
|
-
def replace
|
9
|
-
super do | resource |
|
10
|
-
resource.first_name = OVERRIDDEN_NAME
|
11
|
-
resource.save!
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def storage_class
|
18
|
-
MockUser
|
19
|
-
end
|
20
|
-
|
21
|
-
def storage_scope
|
22
|
-
MockUser.all
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# For tests only - uses custom 'save!' implementation which passes a block to
|
2
|
-
# Scimitar::ActiveRecordBackedResourcesController#save!.
|
3
|
-
#
|
4
|
-
class CustomSaveMockUsersController < Scimitar::ActiveRecordBackedResourcesController
|
5
|
-
|
6
|
-
CUSTOM_SAVE_BLOCK_USERNAME_INDICATOR = 'Custom save-block invoked'
|
7
|
-
|
8
|
-
protected
|
9
|
-
|
10
|
-
def save!(_record)
|
11
|
-
super do | record |
|
12
|
-
record.update!(username: CUSTOM_SAVE_BLOCK_USERNAME_INDICATOR)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def storage_class
|
17
|
-
MockUser
|
18
|
-
end
|
19
|
-
|
20
|
-
def storage_scope
|
21
|
-
MockUser.all
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
# For tests only - uses custom 'update' implementation which passes a block to
|
2
|
-
# Scimitar::ActiveRecordBackedResourcesController#create.
|
3
|
-
#
|
4
|
-
class CustomUpdateMockUsersController < Scimitar::ActiveRecordBackedResourcesController
|
5
|
-
|
6
|
-
OVERRIDDEN_NAME = SecureRandom.uuid
|
7
|
-
|
8
|
-
def update
|
9
|
-
super do | resource |
|
10
|
-
resource.first_name = OVERRIDDEN_NAME
|
11
|
-
resource.save!
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def storage_class
|
18
|
-
MockUser
|
19
|
-
end
|
20
|
-
|
21
|
-
def storage_scope
|
22
|
-
MockUser.all
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|