scimitar 1.0.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 +7 -0
- data/Rakefile +16 -0
- data/app/controllers/scimitar/active_record_backed_resources_controller.rb +180 -0
- data/app/controllers/scimitar/application_controller.rb +129 -0
- data/app/controllers/scimitar/resource_types_controller.rb +28 -0
- data/app/controllers/scimitar/resources_controller.rb +203 -0
- data/app/controllers/scimitar/schemas_controller.rb +16 -0
- data/app/controllers/scimitar/service_provider_configurations_controller.rb +8 -0
- data/app/models/scimitar/authentication_error.rb +9 -0
- data/app/models/scimitar/authentication_scheme.rb +18 -0
- data/app/models/scimitar/bulk.rb +8 -0
- data/app/models/scimitar/complex_types/address.rb +18 -0
- data/app/models/scimitar/complex_types/base.rb +41 -0
- data/app/models/scimitar/complex_types/email.rb +12 -0
- data/app/models/scimitar/complex_types/entitlement.rb +12 -0
- data/app/models/scimitar/complex_types/ims.rb +12 -0
- data/app/models/scimitar/complex_types/name.rb +12 -0
- data/app/models/scimitar/complex_types/phone_number.rb +12 -0
- data/app/models/scimitar/complex_types/photo.rb +12 -0
- data/app/models/scimitar/complex_types/reference_group.rb +12 -0
- data/app/models/scimitar/complex_types/reference_member.rb +12 -0
- data/app/models/scimitar/complex_types/role.rb +12 -0
- data/app/models/scimitar/complex_types/x509_certificate.rb +12 -0
- data/app/models/scimitar/engine_configuration.rb +24 -0
- data/app/models/scimitar/error_response.rb +20 -0
- data/app/models/scimitar/errors.rb +14 -0
- data/app/models/scimitar/filter.rb +11 -0
- data/app/models/scimitar/filter_error.rb +22 -0
- data/app/models/scimitar/invalid_syntax_error.rb +9 -0
- data/app/models/scimitar/lists/count.rb +64 -0
- data/app/models/scimitar/lists/query_parser.rb +730 -0
- data/app/models/scimitar/meta.rb +7 -0
- data/app/models/scimitar/not_found_error.rb +10 -0
- data/app/models/scimitar/resource_invalid_error.rb +9 -0
- data/app/models/scimitar/resource_type.rb +29 -0
- data/app/models/scimitar/resources/base.rb +159 -0
- data/app/models/scimitar/resources/group.rb +13 -0
- data/app/models/scimitar/resources/mixin.rb +964 -0
- data/app/models/scimitar/resources/user.rb +13 -0
- data/app/models/scimitar/schema/address.rb +24 -0
- data/app/models/scimitar/schema/attribute.rb +123 -0
- data/app/models/scimitar/schema/base.rb +86 -0
- data/app/models/scimitar/schema/derived_attributes.rb +24 -0
- data/app/models/scimitar/schema/email.rb +10 -0
- data/app/models/scimitar/schema/entitlement.rb +10 -0
- data/app/models/scimitar/schema/group.rb +27 -0
- data/app/models/scimitar/schema/ims.rb +10 -0
- data/app/models/scimitar/schema/name.rb +20 -0
- data/app/models/scimitar/schema/phone_number.rb +10 -0
- data/app/models/scimitar/schema/photo.rb +10 -0
- data/app/models/scimitar/schema/reference_group.rb +23 -0
- data/app/models/scimitar/schema/reference_member.rb +21 -0
- data/app/models/scimitar/schema/role.rb +10 -0
- data/app/models/scimitar/schema/user.rb +52 -0
- data/app/models/scimitar/schema/vdtp.rb +18 -0
- data/app/models/scimitar/schema/x509_certificate.rb +22 -0
- data/app/models/scimitar/service_provider_configuration.rb +49 -0
- data/app/models/scimitar/supportable.rb +14 -0
- data/app/views/layouts/scimitar/application.html.erb +14 -0
- data/config/initializers/scimitar.rb +82 -0
- data/config/routes.rb +6 -0
- data/lib/scimitar.rb +23 -0
- data/lib/scimitar/engine.rb +63 -0
- data/lib/scimitar/version.rb +13 -0
- data/spec/apps/dummy/app/controllers/custom_destroy_mock_users_controller.rb +24 -0
- data/spec/apps/dummy/app/controllers/custom_request_verifiers_controller.rb +30 -0
- data/spec/apps/dummy/app/controllers/mock_groups_controller.rb +13 -0
- data/spec/apps/dummy/app/controllers/mock_users_controller.rb +13 -0
- data/spec/apps/dummy/app/models/mock_group.rb +83 -0
- data/spec/apps/dummy/app/models/mock_user.rb +104 -0
- data/spec/apps/dummy/config/application.rb +17 -0
- data/spec/apps/dummy/config/boot.rb +2 -0
- data/spec/apps/dummy/config/environment.rb +2 -0
- data/spec/apps/dummy/config/environments/test.rb +15 -0
- data/spec/apps/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/apps/dummy/config/initializers/scimitar.rb +14 -0
- data/spec/apps/dummy/config/initializers/session_store.rb +3 -0
- data/spec/apps/dummy/config/routes.rb +24 -0
- data/spec/apps/dummy/db/migrate/20210304014602_create_mock_users.rb +15 -0
- data/spec/apps/dummy/db/migrate/20210308020313_create_mock_groups.rb +10 -0
- data/spec/apps/dummy/db/migrate/20210308044214_create_join_table_mock_groups_mock_users.rb +8 -0
- data/spec/apps/dummy/db/schema.rb +42 -0
- data/spec/controllers/scimitar/application_controller_spec.rb +173 -0
- data/spec/controllers/scimitar/resource_types_controller_spec.rb +94 -0
- data/spec/controllers/scimitar/resources_controller_spec.rb +247 -0
- data/spec/controllers/scimitar/schemas_controller_spec.rb +75 -0
- data/spec/controllers/scimitar/service_provider_configurations_controller_spec.rb +22 -0
- data/spec/models/scimitar/complex_types/address_spec.rb +19 -0
- data/spec/models/scimitar/complex_types/email_spec.rb +23 -0
- data/spec/models/scimitar/lists/count_spec.rb +147 -0
- data/spec/models/scimitar/lists/query_parser_spec.rb +763 -0
- data/spec/models/scimitar/resource_type_spec.rb +21 -0
- data/spec/models/scimitar/resources/base_spec.rb +289 -0
- data/spec/models/scimitar/resources/base_validation_spec.rb +61 -0
- data/spec/models/scimitar/resources/mixin_spec.rb +2127 -0
- data/spec/models/scimitar/resources/user_spec.rb +55 -0
- data/spec/models/scimitar/schema/attribute_spec.rb +80 -0
- data/spec/models/scimitar/schema/base_spec.rb +64 -0
- data/spec/models/scimitar/schema/group_spec.rb +87 -0
- data/spec/models/scimitar/schema/user_spec.rb +710 -0
- data/spec/requests/active_record_backed_resources_controller_spec.rb +569 -0
- data/spec/requests/application_controller_spec.rb +49 -0
- data/spec/requests/controller_configuration_spec.rb +17 -0
- data/spec/requests/engine_spec.rb +20 -0
- data/spec/spec_helper.rb +66 -0
- metadata +315 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require_dependency "scimitar/application_controller"
|
|
2
|
+
|
|
3
|
+
module Scimitar
|
|
4
|
+
class SchemasController < ApplicationController
|
|
5
|
+
def index
|
|
6
|
+
schemas = Scimitar::Engine.schemas
|
|
7
|
+
schemas_by_id = schemas.reduce({}) do |hash, schema|
|
|
8
|
+
hash[schema.id] = schema
|
|
9
|
+
hash
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
render json: schemas_by_id[params[:name]] || schemas
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
class AuthenticationScheme
|
|
3
|
+
include ActiveModel::Model
|
|
4
|
+
attr_accessor :type, :name, :description
|
|
5
|
+
|
|
6
|
+
def self.basic
|
|
7
|
+
new type: 'httpbasic',
|
|
8
|
+
name: 'HTTP Basic',
|
|
9
|
+
description: 'Authentication scheme using the HTTP Basic Standard'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.bearer
|
|
13
|
+
new type: 'oauthbearertoken',
|
|
14
|
+
name: 'OAuth Bearer Token',
|
|
15
|
+
description: 'Authentication scheme using the OAuth Bearer Token Standard'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
module ComplexTypes
|
|
3
|
+
|
|
4
|
+
# Represents the complex Address type.
|
|
5
|
+
#
|
|
6
|
+
# See also Scimitar::Schema::Address
|
|
7
|
+
#
|
|
8
|
+
class Address < Base
|
|
9
|
+
set_schema Scimitar::Schema::Address
|
|
10
|
+
|
|
11
|
+
# Returns the JSON representation of an Address.
|
|
12
|
+
#
|
|
13
|
+
def as_json(options = {})
|
|
14
|
+
{'type' => 'work'}.merge(super(options))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
module ComplexTypes
|
|
3
|
+
|
|
4
|
+
# This class represents complex types that could be used inside SCIM
|
|
5
|
+
# resources. Each complex type must inherit from this class. They also need
|
|
6
|
+
# to have their own schema defined. For example:
|
|
7
|
+
#
|
|
8
|
+
# module Scimitar
|
|
9
|
+
# module ComplexTypes
|
|
10
|
+
# class Email < Base
|
|
11
|
+
# set_schema Scimitar::Schema::Email
|
|
12
|
+
#
|
|
13
|
+
# def as_json(options = {})
|
|
14
|
+
# {'type' => 'work', 'primary' => true}.merge(super(options))
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
class Base
|
|
21
|
+
include ActiveModel::Model
|
|
22
|
+
include Scimitar::Schema::DerivedAttributes
|
|
23
|
+
include Scimitar::Errors
|
|
24
|
+
|
|
25
|
+
def initialize(options={})
|
|
26
|
+
super
|
|
27
|
+
@errors = ActiveModel::Errors.new(self)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Converts the object to its SCIM representation, which is always JSON.
|
|
31
|
+
#
|
|
32
|
+
# +options+:: A hash that could provide default values for some of the
|
|
33
|
+
# attributes of this complex type object.
|
|
34
|
+
#
|
|
35
|
+
def as_json(options={})
|
|
36
|
+
options[:except] ||= ['errors']
|
|
37
|
+
super.except(options)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
|
|
3
|
+
# Scimitar general configuration.
|
|
4
|
+
#
|
|
5
|
+
# See config/initializers/scimitar.rb for more information.
|
|
6
|
+
#
|
|
7
|
+
class EngineConfiguration
|
|
8
|
+
include ActiveModel::Model
|
|
9
|
+
|
|
10
|
+
attr_accessor :basic_authenticator,
|
|
11
|
+
:token_authenticator,
|
|
12
|
+
:application_controller_mixin
|
|
13
|
+
|
|
14
|
+
def initialize(attributes = {})
|
|
15
|
+
|
|
16
|
+
# No defaults yet - reserved for future use.
|
|
17
|
+
#
|
|
18
|
+
defaults = {}
|
|
19
|
+
|
|
20
|
+
super(defaults.merge(attributes))
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
class ErrorResponse < StandardError
|
|
3
|
+
include ActiveModel::Model
|
|
4
|
+
|
|
5
|
+
attr_accessor :status,
|
|
6
|
+
:detail,
|
|
7
|
+
:scimType
|
|
8
|
+
|
|
9
|
+
def as_json(options = {})
|
|
10
|
+
data = {
|
|
11
|
+
'schemas': ['urn:ietf:params:scim:api:messages:2.0:Error'],
|
|
12
|
+
'detail': detail,
|
|
13
|
+
'status': "#{status}"
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
data['scimType'] = scimType if scimType
|
|
17
|
+
data
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
module Errors
|
|
3
|
+
def add_errors_from_hash(errors_hash, prefix: nil)
|
|
4
|
+
errors_hash.each_pair do |key, value|
|
|
5
|
+
new_key = prefix.nil? ? key : "#{prefix}.#{key}".to_sym
|
|
6
|
+
if value.is_a?(Array)
|
|
7
|
+
value.each {|error| errors.add(new_key, error)}
|
|
8
|
+
else
|
|
9
|
+
errors.add(new_key, value)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
|
|
3
|
+
# Raised when an invalid query is attempted, either by being malformed or by
|
|
4
|
+
# being unsupported in some way.
|
|
5
|
+
#
|
|
6
|
+
class FilterError < ErrorResponse
|
|
7
|
+
def initialize(message = nil)
|
|
8
|
+
detail = 'The specified filter syntax was invalid, or the specified attribute and filter comparison combination is not supported'
|
|
9
|
+
|
|
10
|
+
if message.present?
|
|
11
|
+
detail << ":\n#{message}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
super(
|
|
15
|
+
status: 400,
|
|
16
|
+
scimType: 'invalidFilter',
|
|
17
|
+
detail: detail
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
module Scimitar
|
|
2
|
+
module Lists
|
|
3
|
+
class Count
|
|
4
|
+
include ActiveModel::Model
|
|
5
|
+
|
|
6
|
+
attr_accessor :limit, :start_index, :total
|
|
7
|
+
attr_reader :offset
|
|
8
|
+
|
|
9
|
+
def initialize(*args)
|
|
10
|
+
@limit = 100
|
|
11
|
+
@start_index = 1
|
|
12
|
+
|
|
13
|
+
super(*args)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Set a limit (page size) value.
|
|
17
|
+
#
|
|
18
|
+
# +value+:: Integer value held in a String. Must be >= 1.
|
|
19
|
+
#
|
|
20
|
+
# Raises exceptions if given non-numeric, zero or negative input.
|
|
21
|
+
#
|
|
22
|
+
def limit=(value)
|
|
23
|
+
value = value&.to_s
|
|
24
|
+
return if value.blank? # NOTE EARLY EXIT
|
|
25
|
+
|
|
26
|
+
validate_numericality(value)
|
|
27
|
+
input = value.to_i
|
|
28
|
+
raise if input < 1
|
|
29
|
+
@limit = input
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Set a start index (offset) value. Values start at 1. See also #offset.
|
|
33
|
+
#
|
|
34
|
+
# +value+:: Integer value held in a String. Must be >= 1.
|
|
35
|
+
#
|
|
36
|
+
# Raises exceptions if given non-numeric or negative input. Corrects an
|
|
37
|
+
# input value of zero to 1.
|
|
38
|
+
#
|
|
39
|
+
def start_index=(value)
|
|
40
|
+
value = value&.to_s
|
|
41
|
+
return if value.blank? # NOTE EARLY EXIT
|
|
42
|
+
|
|
43
|
+
validate_numericality(value)
|
|
44
|
+
input = value.to_i
|
|
45
|
+
input = 1 if input < 1
|
|
46
|
+
@start_index = input
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Read-only accessor that represents #start_index as a zero-based offset,
|
|
50
|
+
# rather than 1-based. This is useful for most storage engines.
|
|
51
|
+
#
|
|
52
|
+
def offset
|
|
53
|
+
start_index - 1
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def validate_numericality(input)
|
|
59
|
+
raise unless input.match?(/\A\d+\z/)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|