Class: ScimEngine::Resources::Base

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Model, Errors, Schema::DerivedAttributes
Defined in:
app/models/scim_engine/resources/base.rb

Overview

The base class for all SCIM resources.

Direct Known Subclasses

Group, User

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Errors

#add_errors_from_hash

Constructor Details

#initialize(options = {}) ⇒ Base

Returns a new instance of Base.



13
14
15
16
17
18
19
# File 'app/models/scim_engine/resources/base.rb', line 13

def initialize(options = {})
  flattended_attributes = flatten_extension_attributes(options)
  attributes = flattended_attributes.with_indifferent_access.slice(*self.class.all_attributes)
  super(attributes)
  constantize_complex_types(attributes)
  @errors = ActiveModel::Errors.new(self)
end

Instance Attribute Details

#errorsObject (readonly)

Returns the value of attribute errors.



10
11
12
# File 'app/models/scim_engine/resources/base.rb', line 10

def errors
  @errors
end

#externalIdObject

Returns the value of attribute externalId.



9
10
11
# File 'app/models/scim_engine/resources/base.rb', line 9

def externalId
  @externalId
end

#idObject

Returns the value of attribute id.



9
10
11
# File 'app/models/scim_engine/resources/base.rb', line 9

def id
  @id
end

#metaObject

Returns the value of attribute meta.



9
10
11
# File 'app/models/scim_engine/resources/base.rb', line 9

def meta
  @meta
end

Class Method Details

.all_attributesObject



72
73
74
75
# File 'app/models/scim_engine/resources/base.rb', line 72

def self.all_attributes
  scim_attributes = schemas.map(&:scim_attributes).flatten.map(&:name)
  scim_attributes + [:id, :externalId, :meta]
end

.complex_scim_attributesObject



77
78
79
# File 'app/models/scim_engine/resources/base.rb', line 77

def self.complex_scim_attributes
  schema.scim_attributes.select(&:complexType).group_by(&:name)
end

.extend_schema(schema) ⇒ Object

Can be used to extend an existing resource type’s schema

Examples:

module Scim
  module Schema
    class MyExtension < ScimEngine::Schema::Base

      def initialize(options = {})
        super(name: 'ExtendedGroup',
              id: self.class.id,
              description: 'Represents extra info about a group',
              scim_attributes: self.class.scim_attributes)
      end

      def self.id
        'urn:ietf:params:scim:schemas:extension:extendedgroup:2.0:Group'
      end

      def self.scim_attributes
        [ScimEngine::Schema::Attribute.new(name: 'someAddedAttribute',
                       type: 'string',
                       required: true,
                       canonicalValues: ['FOO', 'BAR'])]
      end
    end
  end
end

ScimEngine::Resources::Group.extend_schema Scim::Schema::MyExtention


59
60
61
62
# File 'app/models/scim_engine/resources/base.rb', line 59

def self.extend_schema(schema)
  derive_attributes_from_schema(schema)
  extended_schemas << schema
end

.extended_schemasObject



64
65
66
# File 'app/models/scim_engine/resources/base.rb', line 64

def self.extended_schemas
  @extended_schemas ||= []
end

.resource_type(location) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
# File 'app/models/scim_engine/resources/base.rb', line 118

def self.resource_type(location)
  resource_type = ResourceType.new(
    endpoint: endpoint,
    schema: schema.id,
    id: resource_type_id,
    name: resource_type_id,
    schemaExtensions: extended_schemas.map(&:id)
  )

  resource_type.meta.location = location
  resource_type
end

.resource_type_idObject



114
115
116
# File 'app/models/scim_engine/resources/base.rb', line 114

def self.resource_type_id
  name.demodulize
end

.schemasObject



68
69
70
# File 'app/models/scim_engine/resources/base.rb', line 68

def self.schemas
  ([schema] + extended_schemas).flatten
end

Instance Method Details

#as_json(options = {}) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
# File 'app/models/scim_engine/resources/base.rb', line 102

def as_json(options = {})
  self.meta = Meta.new unless self.meta
  meta.resourceType = self.class.resource_type_id
  original_hash = super(options).except('errors')
  original_hash.merge!("schemas" => self.class.schemas.map(&:id))
  self.class.extended_schemas.each do |extension_schema|
    extension_attributes = extension_schema.scim_attributes.map(&:name)
    original_hash.merge!(extension_schema.id => original_hash.extract!(*extension_attributes))
  end
  original_hash
end

#complex_type_from_hash(scim_attribute, attr_value) ⇒ Object



81
82
83
84
85
86
87
# File 'app/models/scim_engine/resources/base.rb', line 81

def complex_type_from_hash(scim_attribute, attr_value)
  if attr_value.is_a?(Hash)
    scim_attribute.complexType.new(attr_value)
  else
    attr_value
  end
end

#constantize_complex_types(hash) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
# File 'app/models/scim_engine/resources/base.rb', line 89

def constantize_complex_types(hash)
  hash.with_indifferent_access.each_pair do |attr_name, attr_value|
    scim_attribute = self.class.complex_scim_attributes[attr_name].try(:first)
    if scim_attribute && scim_attribute.complexType
      if scim_attribute.multiValued
        self.send("#{attr_name}=", attr_value.map {|attr_for_each_item| complex_type_from_hash(scim_attribute, attr_for_each_item)})
      else
        self.send("#{attr_name}=", complex_type_from_hash(scim_attribute, attr_value))
      end
    end
  end
end

#flatten_extension_attributes(options) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'app/models/scim_engine/resources/base.rb', line 21

def flatten_extension_attributes(options)
  flattened = options.dup
  self.class.extended_schemas.each do |extended_schema|
    if extension_attrs = flattened.delete(extended_schema.id)
      flattened.merge!(extension_attrs)
    end
  end
  flattened
end

#validate_resourceObject



131
132
133
134
135
136
# File 'app/models/scim_engine/resources/base.rb', line 131

def validate_resource
  self.class.schema.valid?(self)
  self.class.extended_schemas.each do |extended_schema|
    extended_schema.valid?(self)
  end
end