Commit ca66b19
Changed files (8)
app
controllers
scim
models
scim
views
scim
v2
resource_types
config
initializers
spec
requests
scim
app/controllers/scim/v2/resource_types_controller.rb
@@ -2,7 +2,20 @@
module Scim
module V2
- class ResourceTypesController < ApplicationController
+ class ResourceTypesController < ::Scim::Controller
+ def index
+ render status: :ok
+ 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
+ else
+ raise ActiveRecord::RecordNotFound
+ end
+ end
end
end
end
app/models/scim/schema.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module SCIM
+ module Schema
+ ERROR = 'urn:ietf:params:scim:api:messages:2.0:Error'
+ GROUP = 'urn:ietf:params:scim:schemas:core:2.0:Group'
+ RESOURCE_TYPE = 'urn:ietf:params:scim:schemas:core:2.0:ResourceType'
+ USER = 'urn:ietf:params:scim:schemas:core:2.0:User'
+ end
+end
app/views/scim/v2/resource_types/_group.scim.jbuilder
@@ -0,0 +1,13 @@
+# 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
@@ -0,0 +1,13 @@
+# 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
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+json.array! [
+ {
+ "schemas": [SCIM::Schema::RESOURCE_TYPE],
+ "id": "User",
+ "meta": {
+ "location": scim_v2_resource_type_url(id: 'User'),
+ "resourceType": "ResourceType"
+ },
+ "description": "User Account",
+ "endpoint": scim_v2_users_url,
+ "name": "User",
+ "schema": SCIM::Schema::USER,
+ "schemaExtensions": []
+ },
+ {
+ "schemas": [SCIM::Schema::RESOURCE_TYPE],
+ "id": "Group",
+ "meta": {
+ "location": scim_v2_resource_type_url(id: 'Group'),
+ "resourceType": "ResourceType"
+ },
+ "description": "Group",
+ "endpoint": scim_v2_groups_url,
+ "name": "Group",
+ "schema": SCIM::Schema::GROUP,
+ "schemaExtensions": []
+ }
+]
config/initializers/mime_types.rb
@@ -6,7 +6,6 @@
# Mime::Type.register "text/richtext", :rtf
Mime::Type.register "application/scim+json", :scim
-scim_parser = ActionDispatch::Request.parameter_parsers[:json]
-original_parsers = ActionDispatch::Request.parameter_parsers
-ActionDispatch::Request.parameter_parsers =
- original_parsers.merge(Mime[:scim].symbol => scim_parser)
+ActionDispatch::Request.parameter_parsers[:scim] = lambda do |body|
+ JSON.parse(body)
+end
config/routes.rb
@@ -15,12 +15,26 @@ Rails.application.routes.draw do
namespace :scim do
namespace :v2, defaults: { format: :scim } do
post ".search", to: "search#index"
- resources :users, only: [:index, :show, :create, :update, :destroy]
- get :ServiceProviderConfig, to: "service_providers#show"
+
+ get 'Groups/:id', to: 'groups#show'
+ post :Groups, to: "groups#create"
+ put 'Groups/:id', to: "groups#update"
resources :groups, only: [:index]
- resources :resource_types, only: [:index]
+
get :ResourceTypes, to: "resource_types#index"
- resources :schemas, only: [:index]
+ get 'ResourceTypes/:id', to: "resource_types#show"
+ resources :resource_types, only: [:index, :show]
+
+ get :Schemas, to: 'schemas#index'
+ get 'Schemas/:id', to: "schemas#show"
+ resources :schemas, only: [:index, :show]
+
+ get :ServiceProviderConfig, to: "service_providers#show"
+
+ get 'Users/:id', to: 'users#show'
+ post :Users, to: "users#create"
+ put 'Users/:id', to: "users#update"
+ resources :users, only: [:index, :show, :create, :update, :destroy]
match 'Me', to: lambda { |env| [501, {}, ['']] }, via: [:get, :post, :put, :patch, :delete]
match 'Bulk', to: lambda { |env| [501, {}, ['']] }, via: [:post]
spec/requests/scim/v2/resource_types_spec.rb
@@ -0,0 +1,70 @@
+require 'rails_helper'
+
+RSpec.describe "/scim/v2/ResourceTypes" do
+ let(:user) { create(:user) }
+ let(:token) { user.access_token('audience') }
+ let(:headers) do
+ {
+ 'Accept' => 'application/scim+json',
+ 'Content-Type' => 'application/scim+json',
+ 'Authorization' => "Bearer #{token}"
+ }
+ end
+
+ describe "GET /scim/v2/ResourceTypes" do
+ before { get "/scim/v2/ResourceTypes", headers: headers }
+ let(:json) { JSON.parse(response.body, symbolize_names: true) }
+
+ specify { expect(response).to have_http_status(:ok) }
+ specify { expect(json.count).to eql(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') }
+ specify { expect(json[0][:name]).to eql('User') }
+ specify { expect(json[0][:endpoint]).to eql(scim_v2_users_url) }
+ specify { expect(json[0][:meta][:location]).to eql(scim_v2_resource_type_url(id: 'User')) }
+ specify { expect(json[0][:meta][:resourceType]).to eql('ResourceType') }
+
+ specify { expect(json[1][:schemas]).to match_array(["urn:ietf:params:scim:schemas:core:2.0:ResourceType"]) }
+ specify { expect(json[1][:id]).to eql('Group') }
+ specify { expect(json[1][:name]).to eql('Group') }
+ specify { expect(json[1][:schema]).to eql('urn:ietf:params:scim:schemas:core:2.0:Group') }
+ specify { expect(json[1][:endpoint]).to eql(scim_v2_groups_url) }
+ specify { expect(json[1][:meta][:location]).to eql(scim_v2_resource_type_url(id: 'Group')) }
+ specify { expect(json[1][:meta][:resourceType]).to eql('ResourceType') }
+ specify { expect(json[1][:schemaExtensions]).to match_array([]) }
+ end
+
+ describe "GET /scim/v2/ResourceTypes/User" do
+ before { get "/scim/v2/ResourceTypes/User", headers: headers }
+ let(:json) { JSON.parse(response.body, symbolize_names: true) }
+
+ specify { expect(response).to have_http_status(:ok) }
+ 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') }
+ specify { expect(json[:endpoint]).to eql(scim_v2_users_url) }
+ specify { expect(json[:meta][:location]).to eql(scim_v2_resource_type_url(id: 'User')) }
+ specify { expect(json[:meta][:resourceType]).to eql('ResourceType') }
+ end
+
+ describe "GET /scim/v2/ResourceTypes/Group" do
+ before { get "/scim/v2/ResourceTypes/Group", headers: headers }
+ let(:json) { JSON.parse(response.body, symbolize_names: true) }
+
+ specify { expect(response).to have_http_status(:ok) }
+ 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') }
+ specify { expect(json[:endpoint]).to eql(scim_v2_groups_url) }
+ specify { expect(json[:meta][:location]).to eql(scim_v2_resource_type_url(id: 'Group')) }
+ specify { expect(json[:meta][:resourceType]).to eql('ResourceType') }
+ specify { expect(json[:schema]).to eql('urn:ietf:params:scim:schemas:core:2.0:Group') }
+ specify { expect(json[:schemaExtensions]).to match_array([]) }
+ end
+
+ describe "GET /scim/v2/ResourceTypes/unknown" do
+ before { get "/scim/v2/ResourceTypes/unknown", headers: headers }
+
+ specify { expect(response).to have_http_status(:not_found) }
+ end
+end