Skip to content

Commit a51b496

Browse files
authored
Merge pull request tractionguest#22 from tractionguest/feature/idaptive-integration
[SST-15979] Support for Idaptive integration
2 parents 332f91e + 6dd7f91 commit a51b496

File tree

12 files changed

+591
-12
lines changed

12 files changed

+591
-12
lines changed

app/controllers/concerns/scim_rails/response.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ def json_scim_response(object:, status: :ok, counts: nil)
2020
when "delete"
2121
head status
2222
return
23+
when "configuration"
24+
response = ScimRails.config.config_schema
25+
when "resource_user"
26+
response = ScimRails.config.resource_user_schema
27+
when "resource_group"
28+
response = ScimRails.config.resource_group_schema
2329
end
2430

2531
render \
@@ -28,6 +34,13 @@ def json_scim_response(object:, status: :ok, counts: nil)
2834
content_type: CONTENT_TYPE
2935
end
3036

37+
def json_schema_response(object)
38+
render \
39+
json: object,
40+
status: :ok,
41+
content_type: CONTENT_TYPE
42+
end
43+
3144
def json_scim_group_response(object:, status: :ok, counts: nil)
3245
response = nil
3346
case params[:action]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module ScimRails
2+
class ScimResourceController < ScimRails::ApplicationController
3+
def resource_user
4+
ScimRails.config.before_scim_response.call(request.params) if ScimRails.config.before_scim_response.respond_to?(:call)
5+
6+
ScimRails.config.after_scim_response.call(ScimRails.config.resource_user_schema, "RETRIEVED") if ScimRails.config.after_scim_response.respond_to?(:call)
7+
8+
json_scim_response(object: nil)
9+
end
10+
11+
def resource_group
12+
ScimRails.config.before_scim_response.call(request.params) if ScimRails.config.before_scim_response.respond_to?(:call)
13+
14+
ScimRails.config.after_scim_response.call(ScimRails.config.resource_group_schema, "RETRIEVED") if ScimRails.config.after_scim_response.respond_to?(:call)
15+
16+
json_scim_response(object: nil)
17+
end
18+
end
19+
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module ScimRails
2+
class ScimSchemaController < ApplicationController
3+
def get_schema
4+
ScimRails.config.before_scim_response.call(request.params) if ScimRails.config.before_scim_response.respond_to?(:call)
5+
6+
id = request.params.key?("format") ? "#{request.params[:id]}.#{request.params[:format]}" : request.params[:id]
7+
8+
if id == "urn:ietf:params:scim:schemas:core:2.0:User"
9+
object = ScimRails.config.retrievable_user_schema
10+
elsif id == "urn:ietf:params:scim:schemas:core:2.0:Group"
11+
object = ScimRails.config.retrievable_group_schema
12+
else
13+
object = {}
14+
end
15+
16+
ScimRails.config.after_scim_response.call(object, "RETRIEVED") if ScimRails.config.after_scim_response.respond_to?(:call)
17+
18+
json_schema_response(object)
19+
end
20+
end
21+
end
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module ScimRails
2+
class ScimServiceController < ScimRails::ApplicationController
3+
def configuration
4+
ScimRails.config.before_scim_response.call(request.params) unless ScimRails.config.before_scim_response.nil?
5+
6+
ScimRails.config.after_scim_response.call(ScimRails.config.config_schema, "RETRIEVED") unless ScimRails.config.after_scim_response.nil?
7+
8+
json_scim_response(object: nil)
9+
end
10+
end
11+
end

config/routes.rb

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
ScimRails::Engine.routes.draw do
2-
get 'scim/v2/Users', action: :index, controller: 'scim_users'
3-
post 'scim/v2/Users', action: :create, controller: 'scim_users'
4-
get 'scim/v2/Users/:id', action: :show, controller: 'scim_users'
5-
put 'scim/v2/Users/:id', action: :put_update, controller: 'scim_users'
6-
patch 'scim/v2/Users/:id', action: :patch_update, controller: 'scim_users'
7-
delete 'scim/v2/Users/:id', action: :delete, controller: 'scim_users'
2+
get 'scim/v2/Users', action: :index, controller: 'scim_users'
3+
post 'scim/v2/Users', action: :create, controller: 'scim_users'
4+
get 'scim/v2/Users/:id', action: :show, controller: 'scim_users'
5+
put 'scim/v2/Users/:id', action: :put_update, controller: 'scim_users'
6+
patch 'scim/v2/Users/:id', action: :patch_update, controller: 'scim_users'
7+
delete 'scim/v2/Users/:id', action: :delete, controller: 'scim_users'
88

9-
get 'scim/v2/Groups', action: :index, controller: 'scim_groups'
10-
post 'scim/v2/Groups', action: :create, controller: 'scim_groups'
11-
get 'scim/v2/Groups/:id', action: :show, controller: 'scim_groups'
12-
put 'scim/v2/Groups/:id', action: :put_update, controller: 'scim_groups'
13-
patch 'scim/v2/Groups/:id', action: :patch_update, controller: 'scim_groups'
14-
delete 'scim/v2/Groups/:id', action: :delete, controller: 'scim_groups'
9+
get 'scim/v2/Groups', action: :index, controller: 'scim_groups'
10+
post 'scim/v2/Groups', action: :create, controller: 'scim_groups'
11+
get 'scim/v2/Groups/:id', action: :show, controller: 'scim_groups'
12+
put 'scim/v2/Groups/:id', action: :put_update, controller: 'scim_groups'
13+
patch 'scim/v2/Groups/:id', action: :patch_update, controller: 'scim_groups'
14+
delete 'scim/v2/Groups/:id', action: :delete, controller: 'scim_groups'
15+
16+
get 'scim/v2/ServiceProviderConfig', action: :configuration, controller: 'scim_service'
17+
get 'scim/v2/ServiceProviderConfigs', action: :configuration, controller: 'scim_service'
18+
19+
get 'scim/v2/ResourceTypes/User', action: :resource_user, controller: 'scim_resource'
20+
get 'scim/v2/ResourceTypes/Group', action: :resource_group, controller: 'scim_resource'
21+
22+
get 'scim/v2/Schemas/:id', action: :get_schema, controller: 'scim_schema'
1523
end

lib/generators/scim_rails/templates/initializer.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,4 +150,40 @@
150150
config.after_scim_response = lambda do |object, status|
151151
print "#{object} #{status}"
152152
end
153+
154+
config.config_schema = {
155+
schemas: ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
156+
patch: {
157+
supported: true
158+
},
159+
bulk: {
160+
supported: false,
161+
maxOperations: 0,
162+
maxPayloadSize: 0
163+
},
164+
filter: {
165+
supported: true,
166+
},
167+
changePassword: {
168+
supported: false
169+
},
170+
sort: {
171+
supported: true
172+
},
173+
etag: {
174+
supported: false
175+
},
176+
authenticationSchemes: [
177+
{
178+
type: "oauthbearertoken",
179+
name: "Oauth Bearer Token",
180+
description: "Authentication scheme using the OAuth Bearer Token Standard"
181+
},
182+
{
183+
type: "httpbasic",
184+
name: "HTTP Basic",
185+
description: "Authentication scheme using the HTTP Basic Standard"
186+
}
187+
]
188+
}
153189
end

lib/scim_rails/config.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ class Config
4747
:before_scim_response,
4848
:after_scim_response,
4949
:scim_attribute_type_mappings,
50+
:config_schema,
51+
:resource_user_schema,
52+
:resource_group_schema,
53+
:retrievable_user_schema,
54+
:retrievable_group_schema
5055

5156
def initialize
5257
@basic_auth_model = "Company"
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
require "spec_helper"
2+
3+
RSpec.describe ScimRails::ScimResourceController, type: :controller do
4+
include AuthHelper
5+
include CallbackHelper
6+
7+
let!(:counter) { CallbackHelper::CallbackCounter.new }
8+
9+
routes { ScimRails::Engine.routes }
10+
11+
describe "resource_user" do
12+
let(:company) { create(:company) }
13+
14+
context "when unauthorized" do
15+
it "returns scim+json content type" do
16+
get :resource_user
17+
18+
expect(response.content_type).to eq("application/scim+json")
19+
end
20+
21+
it "fails with no credentials" do
22+
get :resource_user
23+
24+
expect(response.status).to eq(401)
25+
end
26+
27+
it "fails with invalid credentials" do
28+
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials("unauthorized","123456")
29+
30+
get :resource_user
31+
32+
expect(response.status).to eq(401)
33+
end
34+
end
35+
36+
context "when authorized" do
37+
let(:body) { JSON.parse(response.body) }
38+
39+
before :each do
40+
http_login(company)
41+
end
42+
43+
it "returns scim+json content type" do
44+
get :resource_user
45+
46+
expect(response.content_type).to eq("application/scim+json")
47+
end
48+
49+
it "is successful with valid credentials" do
50+
get :resource_user
51+
52+
expect(response.status).to eq(200)
53+
end
54+
55+
it "successfully returns the resource schema of users" do
56+
get :resource_user
57+
58+
expect(body.deep_symbolize_keys).to eq(ScimRails.config.resource_user_schema)
59+
end
60+
61+
context "when before_scim_response is defined" do
62+
before do
63+
ScimRails.config.before_scim_response = lambda do |body|
64+
counter.before.call
65+
end
66+
end
67+
68+
after do
69+
ScimRails.config.before_scim_response = nil
70+
end
71+
72+
it "successfully calls before_scim_response" do
73+
expect{ get :resource_user }.to change{ counter.before_called }.from(0).to(1)
74+
end
75+
end
76+
77+
context "when after_scim_response is defined" do
78+
before do
79+
ScimRails.config.after_scim_response = lambda do |object, status|
80+
counter.after.call
81+
end
82+
end
83+
84+
after do
85+
ScimRails.config.after_scim_response = nil
86+
end
87+
88+
it "successfully calls after_scim_response" do
89+
expect{ get :resource_user }.to change{ counter.after_called }.from(0).to(1)
90+
end
91+
end
92+
end
93+
end
94+
95+
describe "resource_group" do
96+
let(:company) { create(:company) }
97+
98+
context "when unauthorized" do
99+
it "returns scim+json content type" do
100+
get :resource_group
101+
102+
expect(response.content_type).to eq("application/scim+json")
103+
end
104+
105+
it "fails with no credentials" do
106+
get :resource_group
107+
108+
expect(response.status).to eq(401)
109+
end
110+
111+
it "fails with invalid credentials" do
112+
request.env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials("unauthorized","123456")
113+
114+
get :resource_group
115+
116+
expect(response.status).to eq(401)
117+
end
118+
end
119+
120+
context "when authorized" do
121+
let(:body) { JSON.parse(response.body) }
122+
123+
before :each do
124+
http_login(company)
125+
end
126+
127+
it "returns scim+json content type" do
128+
get :resource_group
129+
130+
expect(response.content_type).to eq("application/scim+json")
131+
end
132+
133+
it "is successful with valid credentials" do
134+
get :resource_group
135+
136+
expect(response.status).to eq(200)
137+
end
138+
139+
it "successfully returns the resource schema of groups" do
140+
get :resource_group
141+
142+
expect(body.deep_symbolize_keys).to eq(ScimRails.config.resource_group_schema)
143+
end
144+
145+
context "when before_scim_response is defined" do
146+
before do
147+
ScimRails.config.before_scim_response = lambda do |body|
148+
counter.before.call
149+
end
150+
end
151+
152+
after do
153+
ScimRails.config.before_scim_response = nil
154+
end
155+
156+
it "successfully calls before_scim_response" do
157+
expect{ get :resource_group }.to change{ counter.before_called }.from(0).to(1)
158+
end
159+
end
160+
161+
context "when after_scim_response is defined" do
162+
before do
163+
ScimRails.config.after_scim_response = lambda do |object, status|
164+
counter.after.call
165+
end
166+
end
167+
168+
after do
169+
ScimRails.config.after_scim_response = nil
170+
end
171+
172+
it "successfully calls before_scim_response" do
173+
expect{ get :resource_group }.to change{ counter.after_called }.from(0).to(1)
174+
end
175+
end
176+
end
177+
end
178+
end

0 commit comments

Comments
 (0)