scimitar 1.11.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scimitar/active_record_backed_resources_controller.rb +23 -98
  3. data/app/controllers/scimitar/application_controller.rb +17 -44
  4. data/app/controllers/scimitar/resource_types_controller.rb +3 -7
  5. data/app/controllers/scimitar/resources_controller.rb +2 -0
  6. data/app/controllers/scimitar/schemas_controller.rb +3 -366
  7. data/app/controllers/scimitar/service_provider_configurations_controller.rb +1 -0
  8. data/app/models/scimitar/complex_types/address.rb +6 -0
  9. data/app/models/scimitar/engine_configuration.rb +5 -15
  10. data/app/models/scimitar/error_response.rb +0 -12
  11. data/app/models/scimitar/lists/query_parser.rb +13 -113
  12. data/app/models/scimitar/resource_invalid_error.rb +1 -1
  13. data/app/models/scimitar/resources/base.rb +9 -53
  14. data/app/models/scimitar/resources/mixin.rb +59 -646
  15. data/app/models/scimitar/schema/address.rb +0 -1
  16. data/app/models/scimitar/schema/attribute.rb +5 -14
  17. data/app/models/scimitar/schema/base.rb +1 -1
  18. data/app/models/scimitar/schema/name.rb +2 -2
  19. data/app/models/scimitar/schema/user.rb +10 -10
  20. data/app/models/scimitar/schema/vdtp.rb +1 -1
  21. data/app/models/scimitar/service_provider_configuration.rb +3 -14
  22. data/config/initializers/scimitar.rb +3 -69
  23. data/lib/scimitar/engine.rb +12 -57
  24. data/lib/scimitar/support/hash_with_indifferent_case_insensitive_access.rb +10 -140
  25. data/lib/scimitar/version.rb +2 -2
  26. data/lib/scimitar.rb +2 -7
  27. data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +1 -1
  28. data/spec/apps/dummy/app/models/mock_group.rb +1 -1
  29. data/spec/apps/dummy/app/models/mock_user.rb +9 -52
  30. data/spec/apps/dummy/config/application.rb +1 -0
  31. data/spec/apps/dummy/config/environments/test.rb +28 -5
  32. data/spec/apps/dummy/config/initializers/scimitar.rb +10 -90
  33. data/spec/apps/dummy/config/routes.rb +7 -28
  34. data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +1 -11
  35. data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +3 -8
  36. data/spec/apps/dummy/db/schema.rb +4 -12
  37. data/spec/controllers/scimitar/application_controller_spec.rb +3 -126
  38. data/spec/controllers/scimitar/resource_types_controller_spec.rb +4 -8
  39. data/spec/controllers/scimitar/schemas_controller_spec.rb +48 -344
  40. data/spec/models/scimitar/complex_types/address_spec.rb +4 -3
  41. data/spec/models/scimitar/complex_types/email_spec.rb +2 -0
  42. data/spec/models/scimitar/lists/query_parser_spec.rb +9 -146
  43. data/spec/models/scimitar/resources/base_spec.rb +71 -217
  44. data/spec/models/scimitar/resources/base_validation_spec.rb +5 -43
  45. data/spec/models/scimitar/resources/mixin_spec.rb +129 -1508
  46. data/spec/models/scimitar/schema/attribute_spec.rb +3 -22
  47. data/spec/models/scimitar/schema/base_spec.rb +1 -1
  48. data/spec/models/scimitar/schema/user_spec.rb +2 -12
  49. data/spec/requests/active_record_backed_resources_controller_spec.rb +66 -1016
  50. data/spec/requests/application_controller_spec.rb +3 -16
  51. data/spec/requests/engine_spec.rb +0 -75
  52. data/spec/spec_helper.rb +1 -9
  53. data/spec/support/hash_with_indifferent_case_insensitive_access_spec.rb +0 -108
  54. metadata +26 -37
  55. data/LICENSE.txt +0 -21
  56. data/README.md +0 -717
  57. data/lib/scimitar/support/utilities.rb +0 -111
  58. data/spec/apps/dummy/app/controllers/custom_create_mock_users_controller.rb +0 -25
  59. data/spec/apps/dummy/app/controllers/custom_replace_mock_users_controller.rb +0 -25
  60. data/spec/apps/dummy/app/controllers/custom_save_mock_users_controller.rb +0 -24
  61. 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