Revert " [#65747] Make /scim_v2/Schemas endpoint return required by OP schemas."

This reverts commit b249fd36b4.
This commit is contained in:
Pavel Balashou
2025-07-10 18:12:29 +02:00
parent b249fd36b4
commit ed795610be
8 changed files with 383 additions and 545 deletions
@@ -89,27 +89,6 @@ module ScimV2
all_possible_attributes - excluded_attributes - excluded_parents
end
def raise_result_errors_for_scim(result)
result.on_failure do |result|
uniqueness_error = result.errors.find { |e| e.type == :taken }
unauthorized_error = result.errors.find { |e| e.type == :error_unauthorized }
if uniqueness_error.present?
raise Scimitar::ErrorResponse.new(
status: 409,
scimType: "uniqueness",
detail: "Operation failed due to a uniqueness constraint: #{result.message}"
)
elsif unauthorized_error.present?
raise Scimitar::ErrorResponse.new(
status: 403,
detail: "Action forbidden: insufficient permissions."
)
else
raise result.message
end
end
end
end
end
end
+29 -21
View File
@@ -40,15 +40,26 @@ module ScimV2
call = Groups::CreateService
.new(user: User.current, model: group)
.call(group.attributes)
raise_result_errors_for_scim(call)
.on_failure do |result|
uniqueness_error = result.errors.find { |e| e.type == :taken }
if uniqueness_error.present?
raise Scimitar::ErrorResponse.new(
status: 409,
scimType: "uniqueness",
detail: "Operation failed due to a uniqueness constraint: #{result.message}"
)
else
raise result.message
end
end
group = call.result
members = scim_resource.members
if members.present?
raise_result_errors_for_scim(
Groups::AddUsersService
.new(group, current_user: User.system)
.call(ids: members.map(&:value), send_notifications: false)
)
Groups::AddUsersService
.new(group, current_user: User.system)
.call(ids: members.map(&:value), send_notifications: false)
.on_failure { |call| raise call.message }
end
group.to_scim(
@@ -64,11 +75,10 @@ module ScimV2
storage_class.transaction do
group = storage_scope.find(group_id)
group.from_scim!(scim_hash: scim_resource.as_json)
raise_result_errors_for_scim(
Groups::UpdateService
.new(user: User.current, model: group)
.call(user_ids: scim_resource.members.map(&:value))
)
Groups::UpdateService
.new(user: User.current, model: group)
.call(user_ids: scim_resource.members.map(&:value))
.on_failure { |call| raise call.message }
group.reload
group.to_scim(
location: url_for(action: :show, id: group.id),
@@ -84,11 +94,10 @@ module ScimV2
group = storage_scope.find(group_id)
group.from_scim_patch!(patch_hash: patch_hash)
user_ids = group.scim_members.map(&:id)
raise_result_errors_for_scim(
Groups::UpdateService
.new(user: User.current, model: group)
.call(user_ids:)
)
Groups::UpdateService
.new(user: User.current, model: group)
.call(user_ids:)
.on_failure { |call| raise call.message }
group.reload
group.to_scim(
location: url_for(action: :show, id: group.id),
@@ -101,11 +110,10 @@ module ScimV2
def destroy
super do |group_id|
group = storage_scope.find(group_id)
raise_result_errors_for_scim(
Groups::DeleteService
.new(user: User.current, model: group)
.call
)
Groups::DeleteService
.new(user: User.current, model: group)
.call
.on_failure { |call| raise call.message }
end
end
+35 -15
View File
@@ -40,7 +40,19 @@ module ScimV2
call = Users::CreateService
.new(user: User.current, model: user)
.call(user.attributes)
raise_result_errors_for_scim(call)
.on_failure do |result|
uniqueness_error = result.errors.find { |e| e.type == :taken }
if uniqueness_error.present?
raise Scimitar::ErrorResponse.new(
status: 409,
scimType: "uniqueness",
detail: "Operation failed due to a uniqueness constraint: #{result.message}"
)
else
raise result.message
end
end
user = call.result
user.to_scim(
location: url_for(action: :show, id: user.id),
@@ -55,11 +67,10 @@ module ScimV2
storage_class.transaction do
user = storage_scope.find(user_id)
user.from_scim!(scim_hash: scim_resource.as_json)
call = Users::UpdateService
.new(user: User.current, model: user)
.call
raise_result_errors_for_scim(call)
user = call.result
Users::UpdateService
.new(user: User.current, model: user)
.call
.on_failure { |call| raise call.message }
user.to_scim(
location: url_for(action: :show, id: user.id),
include_attributes:
@@ -73,11 +84,10 @@ module ScimV2
storage_class.transaction do
user = storage_scope.find(user_id)
user.from_scim_patch!(patch_hash: patch_hash)
call = Users::UpdateService
.new(user: User.current, model: user)
.call
raise_result_errors_for_scim(call)
user = call.result
Users::UpdateService
.new(user: User.current, model: user)
.call
.on_failure { |call| raise call.message }
user.to_scim(
location: url_for(action: :show, id: user.id),
include_attributes:
@@ -89,10 +99,20 @@ module ScimV2
def destroy
super do |user_id|
user = storage_scope.find(user_id)
call = Users::DeleteService
.new(user: User.current, model: user)
.call
raise_result_errors_for_scim(call)
Users::DeleteService
.new(user: User.current, model: user)
.call
.on_failure do |result|
unauthorized_error = result.errors.find { |e| e.type == :error_unauthorized }
if unauthorized_error.present?
raise Scimitar::ErrorResponse.new(
status: 403,
detail: "User can't be deleted due to permission absence."
)
else
raise result.message
end
end
end
end
+2 -2
View File
@@ -38,10 +38,10 @@ Rails.application.config.to_prepare do
)
Scimitar::Schema::User.singleton_class.class_eval do
prepend ScimitarSchemaExtension::User
prepend ScimitarSchemaExtension
end
Scimitar::Schema::Group.singleton_class.class_eval do
prepend ScimitarSchemaExtension::Group
prepend ScimitarSchemaExtension
end
end
+5 -37
View File
@@ -28,43 +28,11 @@
# See COPYRIGHT and LICENSE files for more details.
#++
class OpenProjectNameSchema < Scimitar::Schema::Base
def self.scim_attributes
@scim_attributes ||= [
Scimitar::Schema::Attribute.new(name: "familyName", caseExact: true, type: "string", required: true),
Scimitar::Schema::Attribute.new(name: "givenName", caseExact: true, type: "string", required: true)
]
end
end
class OpenProjectNameComplexType < Scimitar::ComplexTypes::Base
set_schema OpenProjectNameSchema
end
module ScimitarSchemaExtension
module Group
def scim_attributes
[
Scimitar::Schema::Attribute.new(name: "displayName", caseExact: true, type: "string", required: true),
Scimitar::Schema::Attribute.new(name: "members", multiValued: true, complexType: Scimitar::ComplexTypes::ReferenceMember,
mutability: "readWrite"),
Scimitar::Schema::Attribute.new(name: "externalId", type: "string", caseExact: true, required: true)
]
end
end
module User
def scim_attributes
[
Scimitar::Schema::Attribute.new(name: "userName", caseExact: true, type: "string", uniqueness: "server", required: true),
Scimitar::Schema::Attribute.new(name: "name", caseExact: true, complexType: OpenProjectNameComplexType, required: true),
Scimitar::Schema::Attribute.new(name: "active", type: "boolean"),
Scimitar::Schema::Attribute.new(name: "emails", multiValued: true, complexType: Scimitar::ComplexTypes::Email,
required: true),
Scimitar::Schema::Attribute.new(name: "groups", multiValued: true, complexType: Scimitar::ComplexTypes::ReferenceGroup,
mutability: "readOnly"),
Scimitar::Schema::Attribute.new(name: "externalId", type: "string", caseExact: true, required: true)
]
end
def scim_attributes
super + [Scimitar::Schema::Attribute.new(name: "externalId",
type: "string",
caseExact: true,
required: true)]
end
end
+151 -157
View File
@@ -61,26 +61,26 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
get "/scim_v2/Groups", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to match("Resources" => contain_exactly({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] }, { "displayName" => group_without_external_id.name,
"id" => group_without_external_id.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group_without_external_id.id}",
"created" => group_without_external_id.created_at.iso8601,
"lastModified" => group_without_external_id.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] }),
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 2)
expect(response_body).to match({ "Resources" => contain_exactly({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] }, { "displayName" => group_without_external_id.name,
"id" => group_without_external_id.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group_without_external_id.id}",
"created" => group_without_external_id.created_at.iso8601,
"lastModified" => group_without_external_id.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] }),
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 2 })
end
it "filters results" do
@@ -88,29 +88,29 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
get "/scim_v2/Groups?filter=#{filter}", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("Resources" => [{ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] }],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 1)
expect(response_body).to eq({ "Resources" => [{ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] }],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 1 })
filter = ERB::Util.url_encode('displayName Eq "NONEXISTENT GROUP NAME"')
get "/scim_v2/Groups?filter=#{filter}", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("Resources" => [],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 0)
expect(response_body).to eq({ "Resources" => [],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 0 })
end
end
@@ -120,9 +120,8 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -136,29 +135,29 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
get "/scim_v2/Groups/#{group.id}", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
it "excludes specified attributes" do
get "/scim_v2/Groups/#{group.id}?excludedAttributes=members", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
expect(response_body["members"]).to be_nil
end
end
@@ -169,9 +168,8 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -194,15 +192,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group = Group.find_by(name: group_name)
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
it "creates group without members specified" do
@@ -216,15 +214,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group = Group.find_by(name: group_name)
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
end
@@ -234,9 +232,8 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -255,15 +252,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
get "/scim_v2/Groups/#{group.id}", "", headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
perform_enqueued_jobs
assert_performed_jobs 1
@@ -272,9 +269,9 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Resource \"#{group.id}\" not found",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "404"
{ "detail" => "Resource \"#{group.id}\" not found",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "404" }
)
end
end
@@ -285,9 +282,8 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -315,15 +311,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group.reload
expect(response_body).to match("displayName" => group.name,
"externalId" => new_external_group_id,
"id" => group.id.to_s,
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"members" => contain_exactly({ "value" => user.id.to_s }, { "value" => admin.id.to_s }),
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to match({ "displayName" => group.name,
"externalId" => new_external_group_id,
"id" => group.id.to_s,
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"members" => contain_exactly({ "value" => user.id.to_s }, { "value" => admin.id.to_s }),
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
end
@@ -333,9 +329,8 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -360,15 +355,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group.reload
expect(response_body).to eq("displayName" => group.name,
"externalId" => new_external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => new_external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
it "supports replacing of members" do
@@ -390,15 +385,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group.reload
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user2.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user2.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
it "supports adding of a member" do
@@ -418,16 +413,16 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group.reload
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user1.id.to_s },
{ "value" => user2.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [{ "value" => user1.id.to_s },
{ "value" => user2.id.to_s }],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
it "supports removal of a member" do
@@ -446,15 +441,15 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group.reload
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"members" => [],
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
it "supports removal of a member with exclusion of members list from the response" do
@@ -473,14 +468,14 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
group.reload
expect(response_body).to eq("displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"])
expect(response_body).to eq({ "displayName" => group.name,
"externalId" => external_group_id,
"id" => group.id.to_s,
"meta" => { "location" => "http://test.host/scim_v2/Groups/#{group.id}",
"created" => group.created_at.iso8601,
"lastModified" => group.updated_at.iso8601,
"resourceType" => "Group" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:Group"] })
end
end
@@ -490,9 +485,8 @@ RSpec.describe "SCIM API Groups", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
end
end
+13 -81
View File
@@ -42,93 +42,26 @@ RSpec.describe "SCIM API Schemas", with_ee: [:scim_api] do
describe "GET /scim_v2/Schemas" do
context "with the feature flag enabled", with_flag: { scim_api: true } do
# rubocop:disable Layout/LineLength
it "responds with supported schemas" do
get "/scim_v2/Schemas", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body["totalResults"]).to eq(2)
expect(response_body["schemas"]).to eq(["urn:ietf:params:scim:api:messages:2.0:ListResponse"])
expect(response_body["schemas"]).to eq(["urn:ietf:params:scim:api:messages:2.0:ListResponse"])
group_schema = response_body["Resources"].find { |r| r["name"] == "Group" }
user_schema = response_body["Resources"].find { |r| r["name"] == "User" }
expect(group_schema).to eq(
"name" => "Group",
"id" => "urn:ietf:params:scim:schemas:core:2.0:Group",
"description" => "Represents a Group",
"meta" => { "resourceType" => "Schema",
"location" => "http://test.host/scim_v2/Schemas?name=urn%3Aietf%3Aparams%3Ascim%3Aschemas%3Acore%3A2.0%3AGroup" },
"attributes" => [
{ "multiValued" => false, "required" => true, "caseExact" => true, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "displayName", "type" => "string" },
{ "multiValued" => true,
"required" => false,
"caseExact" => false,
"mutability" => "readWrite",
"uniqueness" => "none",
"returned" => "default",
"type" => "complex",
"subAttributes" => [
{ "multiValued" => false, "required" => true, "caseExact" => false, "mutability" => "immutable", "uniqueness" => "none", "returned" => "default", "name" => "value", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "immutable", "uniqueness" => "none", "returned" => "default", "name" => "type", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "immutable", "uniqueness" => "none", "returned" => "default", "name" => "display", "type" => "string" }
],
"name" => "members" },
{ "multiValued" => false, "required" => true, "caseExact" => true, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "externalId", "type" => "string" }
]
)
expect(user_schema).to eq(
"name" => "User",
"id" => "urn:ietf:params:scim:schemas:core:2.0:User",
"description" => "Represents a User",
"meta" => { "resourceType" => "Schema",
"location" => "http://test.host/scim_v2/Schemas?name=urn%3Aietf%3Aparams%3Ascim%3Aschemas%3Acore%3A2.0%3AUser" },
"attributes" => [
{ "multiValued" => false, "required" => true, "caseExact" => true, "mutability" => "readWrite", "uniqueness" => "server", "returned" => "default", "name" => "userName", "type" => "string" },
{ "multiValued" => false,
"required" => true,
"caseExact" => true,
"mutability" => "readWrite",
"uniqueness" => "none",
"returned" => "default",
"type" => "complex",
"subAttributes" => [
{ "multiValued" => false, "required" => true, "caseExact" => true, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "familyName", "type" => "string" },
{ "multiValued" => false, "required" => true, "caseExact" => true, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "givenName", "type" => "string" }
],
"name" => "name" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "active", "type" => "boolean" },
{ "multiValued" => true,
"required" => true,
"caseExact" => false,
"mutability" => "readWrite",
"uniqueness" => "none",
"returned" => "default",
"type" => "complex",
"subAttributes" => [
{ "multiValued" => false, "required" => true, "caseExact" => false, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "value", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "readOnly", "uniqueness" => "none", "returned" => "default", "name" => "display", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "type", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "primary", "type" => "boolean" }
],
"name" => "emails" },
{ "multiValued" => true,
"required" => false,
"caseExact" => false,
"mutability" => "readOnly",
"uniqueness" => "none",
"returned" => "default",
"type" => "complex",
"subAttributes" => [
{ "multiValued" => false, "required" => true, "caseExact" => false, "mutability" => "readOnly", "uniqueness" => "none", "returned" => "default", "name" => "value", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "readOnly", "uniqueness" => "none", "returned" => "default", "name" => "display", "type" => "string" },
{ "multiValued" => false, "required" => false, "caseExact" => false, "mutability" => "readOnly", "uniqueness" => "none", "returned" => "default", "name" => "type", "type" => "string" }
],
"name" => "groups" },
{ "multiValued" => false, "required" => true, "caseExact" => true, "mutability" => "readWrite", "uniqueness" => "none", "returned" => "default", "name" => "externalId", "type" => "string" }
]
)
external_id_schema = { "multiValued" => false,
"required" => true,
"caseExact" => true,
"mutability" => "readWrite",
"uniqueness" => "none",
"returned" => "default",
"name" => "externalId",
"type" => "string" }
expect(group_schema["attributes"]).to include(external_id_schema)
expect(user_schema["attributes"]).to include(external_id_schema)
end
# rubocop:enable Layout/LineLength
end
context "with the feature flag disabled", with_flag: { scim_api: false } do
@@ -137,9 +70,8 @@ RSpec.describe "SCIM API Schemas", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
end
end
+148 -211
View File
@@ -122,11 +122,11 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
get "/scim_v2/Users?filter=#{filter_with_nonexisting_rows}", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("Resources" => [],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 0)
expect(response_body).to eq({ "Resources" => [],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 0 })
end
it "filters results by externalId" do
@@ -158,11 +158,11 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
get "/scim_v2/Users?filter=#{filter_with_nonexisting_rows}", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("Resources" => [],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 0)
expect(response_body).to eq({ "Resources" => [],
"itemsPerPage" => 100,
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
"startIndex" => 1,
"totalResults" => 0 })
end
end
@@ -172,9 +172,8 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -188,21 +187,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
get "/scim_v2/Users/#{user.id}", {}, headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => user.mail }],
"externalId" => external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login)
expect(response_body).to eq({ "active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => user.mail }],
"externalId" => external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login })
end
end
@@ -212,9 +211,8 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -249,71 +247,14 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
expect(last_response).to have_http_status(409)
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail" => "Operation failed due to a uniqueness constraint: Username has already been taken.",
"status" => "409",
"scimType" => "uniqueness"
{ "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail" => "Operation failed due to a uniqueness constraint: Username has already been taken.",
"status" => "409",
"scimType" => "uniqueness" }
)
end
end
it "responds with 400 when email is missing" do
group
request_body = {
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"externalId" => external_user_id,
"userName" => user.login,
"name" => {
"givenName" => "John",
"familyName" => "Doe"
},
"active" => true,
"emails" => []
}
post "/scim_v2/Users/", request_body.to_json, headers
expect(last_response).to have_http_status(400)
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail" => "Invalid resource: Emails is required.",
"status" => "400",
"scimType" => "invalidValue"
)
end
it "responds with 400 when familyName is missing" do
group
request_body = {
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"externalId" => external_user_id,
"userName" => user.login,
"name" => {
"givenName" => "John"
},
"active" => true,
"emails" => [
{
"value" => "jdoe@example.com",
"type" => "work",
"primary" => true
}
]
}
post "/scim_v2/Users/", request_body.to_json, headers
expect(last_response).to have_http_status(400)
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail" => "Invalid resource: Name familyname is required.",
"status" => "400",
"scimType" => "invalidValue"
)
end
it "creates user with provided data and excludes some attributes" do
request_body = {
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
@@ -337,17 +278,17 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
created_user = User.find_by(login: "jdoe")
expect(created_user).to be_present
expect(response_body).to eq("active" => true,
"externalId" => external_user_id,
"groups" => [],
"id" => created_user.id.to_s,
"meta" => { "created" => created_user.created_at.iso8601,
"lastModified" => created_user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{created_user.id}",
"resourceType" => "User" },
"name" => { "familyName" => "Doe" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => "jdoe")
expect(response_body).to eq({ "active" => true,
"externalId" => external_user_id,
"groups" => [],
"id" => created_user.id.to_s,
"meta" => { "created" => created_user.created_at.iso8601,
"lastModified" => created_user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{created_user.id}",
"resourceType" => "User" },
"name" => { "familyName" => "Doe" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => "jdoe" })
end
it "creates user with provided data" do
@@ -373,21 +314,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
created_user = User.find_by(login: "jdoe")
expect(created_user).to be_present
expect(response_body).to eq("active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => "jdoe@example.com" }],
"externalId" => external_user_id,
"groups" => [],
"id" => created_user.id.to_s,
"meta" => { "created" => created_user.created_at.iso8601,
"lastModified" => created_user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{created_user.id}",
"resourceType" => "User" },
"name" => { "familyName" => "Doe",
"givenName" => "John" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => "jdoe")
expect(response_body).to eq({ "active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => "jdoe@example.com" }],
"externalId" => external_user_id,
"groups" => [],
"id" => created_user.id.to_s,
"meta" => { "created" => created_user.created_at.iso8601,
"lastModified" => created_user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{created_user.id}",
"resourceType" => "User" },
"name" => { "familyName" => "Doe",
"givenName" => "John" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => "jdoe" })
end
it "creates user with any email type string provided" do
@@ -411,21 +352,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
created_user = User.find_by(login: "jdoe")
expect(response_body).to eq("active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => "jdoe@example.com" }],
"externalId" => external_user_id,
"groups" => [],
"id" => created_user.id.to_s,
"meta" => { "created" => created_user.created_at.iso8601,
"lastModified" => created_user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{created_user.id}",
"resourceType" => "User" },
"name" => { "familyName" => "Doe",
"givenName" => "John" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => "jdoe")
expect(response_body).to eq({ "active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => "jdoe@example.com" }],
"externalId" => external_user_id,
"groups" => [],
"id" => created_user.id.to_s,
"meta" => { "created" => created_user.created_at.iso8601,
"lastModified" => created_user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{created_user.id}",
"resourceType" => "User" },
"name" => { "familyName" => "Doe",
"givenName" => "John" },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => "jdoe" })
end
end
@@ -435,9 +376,8 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -458,21 +398,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
get "/scim_v2/Users/#{user.id}", "", headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("active" => false,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => user.mail }],
"externalId" => external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login)
expect(response_body).to eq({ "active" => false,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => user.mail }],
"externalId" => external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login })
perform_enqueued_jobs
assert_performed_jobs 1
@@ -481,9 +421,9 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Resource \"#{user.id}\" not found",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "404"
{ "detail" => "Resource \"#{user.id}\" not found",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "404" }
)
end
end
@@ -494,9 +434,9 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
delete "/scim_v2/Users/#{user.id}", "", headers
response_body = JSON.parse(last_response.body)
expect(response_body).to eq("schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail" => "Action forbidden: insufficient permissions.",
"status" => "403")
expect(response_body).to eq({ "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"detail" => "User can't be deleted due to permission absence.",
"status" => "403" })
expect(last_response).to have_http_status(403)
end
end
@@ -508,9 +448,8 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -546,21 +485,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
user.reload
expect(response_body).to eq("active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => request_body["emails"].first["value"] }],
"externalId" => new_external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => request_body["name"]["familyName"],
"givenName" => request_body["name"]["givenName"] },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => request_body["userName"])
expect(response_body).to eq({ "active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => request_body["emails"].first["value"] }],
"externalId" => new_external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => request_body["name"]["familyName"],
"givenName" => request_body["name"]["givenName"] },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => request_body["userName"] })
end
end
@@ -570,9 +509,8 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end
@@ -599,21 +537,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
user.reload
expect(response_body).to eq("active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => user.mail }],
"externalId" => new_external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login)
expect(response_body).to eq({ "active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => user.mail }],
"externalId" => new_external_user_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login })
end
it "changes email value" do
@@ -636,21 +574,21 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
user.reload
expect(response_body).to eq("active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => new_email_value }],
"externalId" => user.scim_external_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login)
expect(response_body).to eq({ "active" => true,
"emails" => [{ "primary" => true,
"type" => "work",
"value" => new_email_value }],
"externalId" => user.scim_external_id,
"groups" => [{ "value" => group.id.to_s }],
"id" => user.id.to_s,
"meta" => { "created" => user.created_at.iso8601,
"lastModified" => user.updated_at.iso8601,
"location" => "http://test.host/scim_v2/Users/#{user.id}",
"resourceType" => "User" },
"name" => { "familyName" => user.lastname,
"givenName" => user.firstname },
"schemas" => ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName" => user.login })
end
end
@@ -660,9 +598,8 @@ RSpec.describe "SCIM API Users", with_ee: [:scim_api] do
response_body = JSON.parse(last_response.body)
expect(response_body).to eq(
"detail" => "Requires authentication",
"schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401"
{ "detail" => "Requires authentication", "schemas" => ["urn:ietf:params:scim:api:messages:2.0:Error"],
"status" => "401" }
)
expect(last_response).to have_http_status(401)
end