Commit 8b6c5a6

mo <mo.khan@gmail.com>
2018-12-26 20:35:28
use scim-kit
1 parent f76ed84
app/controllers/scim/v2/resource_types_controller.rb
@@ -6,19 +6,46 @@ module Scim
       skip_before_action :authenticate!
 
       def index
-        @resource_types = [:user, :group]
-        render status: :ok
+        render status: :ok, json: [user_resource, group_resource].to_json
       end
 
       def show
-        if params[:id] == 'User'
-          render partial: 'user', formats: :scim, status: :ok
-        elsif params[:id] == 'Group'
-          render partial: 'group', formats: :scim, status: :ok
+        render status: :ok, json: current_resource.to_json
+      end
+
+      private
+
+      def current_resource(id = params[:id])
+        if id == 'User'
+          user_resource
+        elsif id == 'Group'
+          group_resource
         else
           raise ActiveRecord::RecordNotFound
         end
       end
+
+      def user_resource
+        location = scim_v2_resource_type_url(id: 'User')
+        Scim::Kit::V2::ResourceType.build(location: location) do |x|
+          x.id = 'User'
+          x.name = 'User'
+          x.schema = SCIM::Schema::USER
+          x.description = 'User Account'
+          x.endpoint = scim_v2_users_url
+        end
+      end
+
+      def group_resource
+        location = scim_v2_resource_type_url(id: 'Group')
+        Scim::Kit::V2::ResourceType.build(location: location) do |x|
+          x.id = 'Group'
+          x.name = 'Group'
+          x.schema = SCIM::Schema::GROUP
+          x.description = 'Group'
+          x.endpoint = scim_v2_groups_url
+        end
+      end
     end
   end
 end
app/controllers/scim/v2/schemas_controller.rb
@@ -6,21 +6,97 @@ module Scim
       skip_before_action :authenticate!
 
       def index
-        @schemas = [:user, :group]
-        render status: :ok
+        render json: [user_schema, group_schema].to_json
       end
 
       def show
-        render partial: 'schema', formats: :scim, status: :ok, locals: {
-          schema: current_schema
-        }
+        render json: current_schema.to_json
       end
 
       private
 
       def current_schema(url = request.original_url)
-        return :group if url.include?(SCIM::Schema::GROUP)
-        return :user if url.include?(SCIM::Schema::USER)
+        return group_schema if url.include?(Scim::Kit::V2::Schema::GROUP)
+        return user_schema if url.include?(Scim::Kit::V2::Schema::USER)
+      end
+
+      def user_schema
+        Scim::Kit::V2::Schema.build(
+          id: Scim::Kit::V2::Schema::USER,
+          name: "User",
+          location: scim_v2_schema_url(id: Scim::Kit::V2::Schema::USER)
+        ) do |schema|
+          schema.description = "User Account"
+          schema.add_attribute(name: 'userName') do |x|
+            x.description = "Unique identifier for the User"
+            x.required = true
+            x.uniqueness = :server
+          end
+          schema.add_attribute(name: 'password') do |x|
+            x.description = "The User's cleartext password."
+            x.mutability = :write_only
+            x.required = false
+            x.returned = :never
+          end
+          schema.add_attribute(name: 'emails') do |x|
+            x.multi_valued = true
+            x.description = "Email addresses for the user."
+            x.add_attribute(name: 'value') do |y|
+              y.description = "Email addresses for the user."
+            end
+            x.add_attribute(name: 'primary', type: :boolean) do |y|
+              y.description = "A Boolean value indicating the preferred email"
+            end
+          end
+          schema.add_attribute(name: 'groups') do |x|
+            x.multi_valued = true
+            x.description = "A list of groups to which the user belongs."
+            x.mutability = :read_only
+            x.add_attribute(name: 'value') do |y|
+              y.description = "The identifier of the User's group."
+              y.mutability = :read_only
+            end
+            x.add_attribute(name: '$ref', type: :reference) do |y|
+              y.reference_types = %w[User Group]
+              y.description = "The URI of the corresponding 'Group' resource."
+              y.mutability = :read_only
+            end
+            x.add_attribute(name: 'display') do |y|
+              y.description = "A human-readable name."
+              y.mutability = :read_only
+            end
+          end
+        end
+      end
+
+      def group_schema
+        Scim::Kit::V2::Schema.new(
+          id: Scim::Kit::V2::Schema::GROUP,
+          name: "Group",
+          location: scim_v2_schema_url(id: Scim::Kit::V2::Schema::GROUP)
+        ) do |schema|
+          schema.description = "Group"
+          schema.add_attribute(name: 'displayName') do |x|
+            x.description = "A human-readable name for the Group."
+          end
+          schema.add_attribute(name: 'members') do |x|
+            x.description = "A list of members of the Group."
+            x.add_attribute(name: 'value') do |y|
+              y.description = "Identifier of the member of this Group."
+              y.mutability = :immutable
+            end
+            x.add_attribute(name: '$ref') do |y|
+              y.description = "The URI corresponding to a SCIM resource."
+              y.reference_types = %w[User Group]
+              y.mutability = :immutable
+            end
+            x.add_attribute(name: 'type') do |y|
+              y.description = "A label indicating the type of resource"
+              y.canonical_values = %w[User Group]
+              y.mutability = :immutable
+            end
+          end
+        end
       end
     end
   end
app/views/scim/v2/resource_types/_group.scim.jbuilder
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-json.schemas [SCIM::Schema::RESOURCE_TYPE]
-json.id "Group"
-json.meta do
-  json.location scim_v2_resource_type_url(id: 'Group')
-  json.resourceType "ResourceType"
-end
-json.description "Group"
-json.endpoint scim_v2_groups_url
-json.name "Group"
-json.schema SCIM::Schema::GROUP
-json.schemaExtensions []
app/views/scim/v2/resource_types/_user.scim.jbuilder
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-json.schemas [SCIM::Schema::RESOURCE_TYPE]
-json.id "User"
-json.meta do
-  json.location scim_v2_resource_type_url(id: 'User')
-  json.resourceType "ResourceType"
-end
-json.description "User Account"
-json.endpoint scim_v2_users_url
-json.name "User"
-json.schema SCIM::Schema::USER
-json.schemaExtensions []
app/views/scim/v2/resource_types/index.scim.jbuilder
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-json.array! @resource_types do |resource_type|
-  json.partial! resource_type.to_s
-end
app/views/scim/v2/schemas/_group.scim.jbuilder
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-json.id SCIM::Schema::GROUP
-json.meta do
-  json.resourceType "Schema"
-  json.location scim_v2_schema_url(id: SCIM::Schema::GROUP)
-end
-json.name "Group"
-json.description "Group"
-json.attributes [
-  {
-    "name": "displayName",
-    "type": "string",
-    "multiValued": false,
-    "description": "A human-readable name for the Group.",
-    "required": false,
-    "caseExact": false,
-    "mutability": "readWrite",
-    "returned": "default",
-    "uniqueness": "none"
-  },
-  {
-    "name": "members",
-    "type": "complex",
-    "multiValued": true,
-    "description": "A list of members of the Group.",
-    "required": false,
-    "subAttributes": [
-      {
-        "name": "value",
-        "type": "string",
-        "multiValued": false,
-        "description": "Identifier of the member of this Group.",
-        "required": false,
-        "caseExact": false,
-        "mutability": "immutable",
-        "returned": "default",
-        "uniqueness": "none"
-      },
-      {
-        "name": "$ref",
-        "type": "reference",
-        "referenceTypes": %w[
-          User
-          Group
-        ],
-        "multiValued": false,
-        "description": "The URI corresponding to a SCIM resource.",
-        "required": false,
-        "caseExact": false,
-        "mutability": "immutable",
-        "returned": "default",
-        "uniqueness": "none"
-      },
-      {
-        "name": "type",
-        "type": "string",
-        "multiValued": false,
-        "description": "A label indicating the type of resource",
-        "required": false,
-        "caseExact": false,
-        "canonicalValues": %w[
-          User
-          Group
-        ],
-        "mutability": "immutable",
-        "returned": "default",
-        "uniqueness": "none"
-      }
-    ],
-    "mutability": "readWrite",
-    "returned": "default"
-  }
-]
app/views/scim/v2/schemas/_schema.scim.jbuilder
@@ -1,8 +0,0 @@
-# frozen_string_literal: true
-
-case schema
-when :group
-  json.partial! 'group'
-when :user
-  json.partial! 'user'
-end
app/views/scim/v2/schemas/_user.scim.jbuilder
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-json.id SCIM::Schema::USER
-json.meta do
-  json.resourceType "Schema"
-  json.location scim_v2_schema_url(id: SCIM::Schema::USER)
-end
-json.name "User"
-json.description "User Account"
-json.attributes [
-  {
-    "name": "userName",
-    "type": "string",
-    "multiValued": false,
-    "description": "Unique identifier for the User",
-    "required": true,
-    "caseExact": false,
-    "mutability": "readWrite",
-    "returned": "default",
-    "uniqueness": "server"
-  },
-  {
-    "name": "password",
-    "type": "string",
-    "multiValued": false,
-    "description": "The User's cleartext password.",
-    "required": false,
-    "caseExact": false,
-    "mutability": "writeOnly",
-    "returned": "never",
-    "uniqueness": "none"
-  },
-  {
-    "name": "emails",
-    "type": "complex",
-    "multiValued": true,
-    "description": "Email addresses for the user.",
-    "required": false,
-    "subAttributes": [
-      {
-        "name": "value",
-        "type": "string",
-        "multiValued": false,
-        "description": "Email addresses for the user.",
-        "required": false,
-        "caseExact": false,
-        "mutability": "readWrite",
-        "returned": "default",
-        "uniqueness": "none"
-      },
-      {
-        "name": "primary",
-        "type": "boolean",
-        "multiValued": false,
-        "description": "A Boolean value indicating the preferred email",
-        "required": false,
-        "mutability": "readWrite",
-        "returned": "default"
-      }
-    ],
-    "mutability": "readWrite",
-    "returned": "default",
-    "uniqueness": "none"
-  },
-  {
-    "name": "groups",
-    "type": "complex",
-    "multiValued": true,
-    "description": "A list of groups to which the user belongs.",
-    "required": false,
-    "subAttributes": [
-      {
-        "name": "value",
-        "type": "string",
-        "multiValued": false,
-        "description": "The identifier of the User's group.",
-        "required": false,
-        "caseExact": false,
-        "mutability": "readOnly",
-        "returned": "default",
-        "uniqueness": "none"
-      },
-      {
-        "name": "$ref",
-        "type": "reference",
-        "referenceTypes": %w[
-          User
-          Group
-        ],
-        "multiValued": false,
-        "description": "The URI of the corresponding 'Group' resource.",
-        "required": false,
-        "caseExact": false,
-        "mutability": "readOnly",
-        "returned": "default",
-        "uniqueness": "none"
-      },
-      {
-        "name": "display",
-        "type": "string",
-        "multiValued": false,
-        "description": "A human-readable name.",
-        "required": false,
-        "caseExact": false,
-        "mutability": "readOnly",
-        "returned": "default",
-        "uniqueness": "none"
-      }
-    ],
-    "mutability": "readOnly",
-    "returned": "default"
-  }
-]
app/views/scim/v2/schemas/index.scim.jbuilder
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-
-json.array! @schemas, partial: 'schema', as: :schema
spec/requests/scim/v2/resource_types_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe "/scim/v2/ResourceTypes" do
     let(:json) { JSON.parse(response.body, symbolize_names: true) }
 
     specify { expect(response).to have_http_status(:ok) }
+    specify { expect(response.content_type).to eql('application/scim+json') }
     specify { expect(json.count).to be(2) }
     specify { expect(json[0][:schemas]).to match_array(["urn:ietf:params:scim:schemas:core:2.0:ResourceType"]) }
     specify { expect(json[0][:id]).to eql('User') }
@@ -40,6 +41,7 @@ RSpec.describe "/scim/v2/ResourceTypes" do
     let(:json) { JSON.parse(response.body, symbolize_names: true) }
 
     specify { expect(response).to have_http_status(:ok) }
+    specify { expect(response.content_type).to eql('application/scim+json') }
     specify { expect(json[:schemas]).to match_array(["urn:ietf:params:scim:schemas:core:2.0:ResourceType"]) }
     specify { expect(json[:id]).to eql('User') }
     specify { expect(json[:name]).to eql('User') }
@@ -54,6 +56,7 @@ RSpec.describe "/scim/v2/ResourceTypes" do
     let(:json) { JSON.parse(response.body, symbolize_names: true) }
 
     specify { expect(response).to have_http_status(:ok) }
+    specify { expect(response.content_type).to eql('application/scim+json') }
     specify { expect(json[:schemas]).to match_array(["urn:ietf:params:scim:schemas:core:2.0:ResourceType"]) }
     specify { expect(json[:id]).to eql('Group') }
     specify { expect(json[:name]).to eql('Group') }
.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: ruby:2.5
+image: ruby:2.6
 
 before_script:
   - curl -sL https://deb.nodesource.com/setup_10.x | bash -
.ruby-version
@@ -1,1 +1,1 @@
-2.5.3
+2.6.0
.travis.yml
@@ -8,7 +8,7 @@ addons:
   postgresql: '9.6'
   chrome: stable
 rvm:
-  - 2.5.3
+  - 2.6.0
 install:
   - nvm install node
   - npm install -g yarn
Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.5-alpine
+FROM ruby:2.6-alpine
 ENV RAILS_ENV production
 ENV RAILS_LOG_TO_STDOUT true
 ENV RAILS_SERVE_STATIC_FILES true
Gemfile
@@ -2,7 +2,7 @@
 
 source 'https://rubygems.org'
 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
-ruby '2.5.3'
+ruby '2.6.0'
 
 gem 'activerecord-session_store', '~> 1.1'
 gem 'audited', '~> 4.8'
@@ -20,6 +20,7 @@ gem 'puma', '~> 3.11'
 gem 'rails', '~> 5.2.0'
 gem 'rotp', '~> 3.3'
 gem 'saml-kit', '~> 1.0'
+gem 'scim-kit'
 gem 'scim-shady', '~> 0.2'
 gem 'spank', '~> 1.0'
 gem 'turbolinks', '~> 5'
Gemfile.lock
@@ -288,6 +288,9 @@ GEM
     sass-listen (4.0.0)
       rb-fsevent (~> 0.9, >= 0.9.4)
       rb-inotify (~> 0.9, >= 0.9.7)
+    scim-kit (0.1.0)
+      tilt (~> 2.0)
+      tilt-jbuilder (~> 0.7)
     scim-shady (0.2.1)
       activesupport (>= 4.2.0)
     selenium-webdriver (3.141.0)
@@ -307,6 +310,9 @@ GEM
     thor (0.20.3)
     thread_safe (0.3.6)
     tilt (2.0.9)
+    tilt-jbuilder (0.7.1)
+      jbuilder
+      tilt (>= 1.3.0, < 3)
     turbolinks (5.2.0)
       turbolinks-source (~> 5.2)
     turbolinks-source (5.2.0)
@@ -377,6 +383,7 @@ DEPENDENCIES
   rubocop (~> 0.59)
   rubocop-rspec (~> 1.30)
   saml-kit (~> 1.0)
+  scim-kit
   scim-shady (~> 0.2)
   selenium-webdriver (~> 3.14)
   spank (~> 1.0)
@@ -387,7 +394,7 @@ DEPENDENCIES
   webpacker (~> 3.5)
 
 RUBY VERSION
-   ruby 2.5.3p105
+   ruby 2.6.0p0
 
 BUNDLED WITH
-   1.17.1
+   1.17.2