scimaenaga 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -8
- data/app/controllers/scim_rails/scim_users_controller.rb +55 -46
- data/app/libraries/scim_patch.rb +28 -0
- data/app/libraries/scim_patch_operation.rb +55 -0
- data/lib/scim_rails/version.rb +1 -1
- data/spec/controllers/scim_rails/scim_users_controller_spec.rb +39 -22
- data/spec/libraries/scim_patch_operation_spec.rb +86 -0
- data/spec/libraries/scim_patch_spec.rb +72 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1fa2914fdf977f0496f84a023f14ba49f61c893683fd04a85ca7ea4a35c4641
|
4
|
+
data.tar.gz: 0c23e5d65e10a641d965e34a0cc78fc72c0c5d9e80a438ba86a1aa59f70e4360
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98e1cecc1b60630c69c78380a59492f9dd293c25b267f16d985bcb76570cac0549648781dd9d3f749713df9e40df329349f88708af1e953ec65b7b18ec560648
|
7
|
+
data.tar.gz: 86d28c8634b38f8af5d85d7670b27e3e7caac314dc90131cd6de9910a284a66dd7a5763ee222c0a8c5adfcafc382b4a919c082fe7f150614359c9f95d1535e59
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
[![Tests](https://github.com/StudistCorporation/
|
2
|
-
[![Inline docs](http://inch-ci.org/github/lessonly/scim_rails.svg?branch=master)](http://inch-ci.org/github/lessonly/scim_rails)
|
3
|
-
[![Maintainability](https://api.codeclimate.com/v1/badges/ddfb6a891d2f0d1122ae/maintainability)](https://codeclimate.com/github/lessonly/scim_rails/maintainability)
|
1
|
+
[![Tests](https://github.com/StudistCorporation/scimaenaga/actions/workflows/test.yaml/badge.svg)](https://github.com/StudistCorporation/scimaenaga/actions/workflows/test.yaml)
|
4
2
|
|
5
|
-
#
|
3
|
+
# Scimaenaga
|
6
4
|
|
7
5
|
NOTE: This Gem is not yet fully SCIM complaint. It was developed with the main function of interfacing with Okta. There are features of SCIM that this Gem does not implement as described in the SCIM documentation or that have been left out completely.
|
8
6
|
|
@@ -19,7 +17,7 @@ The goal of the Gem is to offer a relatively painless way of adding SCIM 2.0 to
|
|
19
17
|
Add this line to your application's Gemfile:
|
20
18
|
|
21
19
|
```ruby
|
22
|
-
gem 'scim_rails'
|
20
|
+
gem 'scimaenaga', require: 'scim_rails'
|
23
21
|
```
|
24
22
|
|
25
23
|
And then execute:
|
@@ -31,7 +29,7 @@ $ bundle
|
|
31
29
|
Or install it yourself as:
|
32
30
|
|
33
31
|
```bash
|
34
|
-
$ gem install
|
32
|
+
$ gem install scimaenaga
|
35
33
|
```
|
36
34
|
|
37
35
|
Generate the config file with:
|
@@ -252,7 +250,7 @@ $ curl -X PATCH 'http://username:password@localhost:3000/scim/v2/Users/1' -d '{"
|
|
252
250
|
|
253
251
|
### Error Handling
|
254
252
|
|
255
|
-
By default,
|
253
|
+
By default, scimaenaga will output any unhandled exceptions to your configured rails logs.
|
256
254
|
|
257
255
|
If you would like, you can supply a custom handler for exceptions in the initializer. The only requirement is that the value you supply responds to `#call`.
|
258
256
|
|
@@ -266,7 +264,7 @@ end
|
|
266
264
|
|
267
265
|
## Contributing
|
268
266
|
|
269
|
-
### [Code of Conduct](https://github.com/
|
267
|
+
### [Code of Conduct](https://github.com/StudistCorporation/scimaenaga/blob/master/CODE_OF_CONDUCT.md)
|
270
268
|
|
271
269
|
### Pull Requests
|
272
270
|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ScimRails
|
4
|
-
class ScimUsersController < ScimRails::ApplicationController
|
4
|
+
class ScimUsersController < ScimRails::ApplicationController # rubocop:disable Metrics/ClassLength
|
5
|
+
# rubocop:disable Metrics/AbcSize
|
6
|
+
# rubocop:disable Metrics/MethodLength
|
5
7
|
def index
|
6
8
|
if params[:filter].present?
|
7
9
|
query = ScimRails::ScimQueryParser.new(
|
@@ -11,7 +13,8 @@ module ScimRails
|
|
11
13
|
users = @company
|
12
14
|
.public_send(ScimRails.config.scim_users_scope)
|
13
15
|
.where(
|
14
|
-
"#{ScimRails.config.scim_users_model
|
16
|
+
"#{ScimRails.config.scim_users_model
|
17
|
+
.connection.quote_column_name(query.attribute)} #{query.operator} ?",
|
15
18
|
query.parameter
|
16
19
|
)
|
17
20
|
.order(ScimRails.config.scim_users_list_order)
|
@@ -32,7 +35,9 @@ module ScimRails
|
|
32
35
|
|
33
36
|
def create
|
34
37
|
if ScimRails.config.scim_user_prevent_update_on_create
|
35
|
-
user = @company
|
38
|
+
user = @company
|
39
|
+
.public_send(ScimRails.config.scim_users_scope)
|
40
|
+
.create!(permitted_user_params)
|
36
41
|
else
|
37
42
|
username_key = ScimRails.config.queryable_user_attributes[:userName]
|
38
43
|
find_by_username = {}
|
@@ -45,6 +50,8 @@ module ScimRails
|
|
45
50
|
update_status(user) unless put_active_param.nil?
|
46
51
|
json_scim_response(object: user, status: :created)
|
47
52
|
end
|
53
|
+
# rubocop:enable Metrics/AbcSize
|
54
|
+
# rubocop:enable Metrics/MethodLength
|
48
55
|
|
49
56
|
def show
|
50
57
|
user = @company.public_send(ScimRails.config.scim_users_scope).find(params[:id])
|
@@ -58,67 +65,69 @@ module ScimRails
|
|
58
65
|
json_scim_response(object: user)
|
59
66
|
end
|
60
67
|
|
61
|
-
# TODO: PATCH will only deprovision or reprovision users.
|
62
|
-
# This will work just fine for Okta but is not SCIM compliant.
|
63
68
|
def patch_update
|
64
69
|
user = @company.public_send(ScimRails.config.scim_users_scope).find(params[:id])
|
65
|
-
|
70
|
+
patch = ScimPatch.new(params, ScimRails.config.mutable_user_attributes_schema)
|
71
|
+
patch.apply(user)
|
72
|
+
user.save
|
73
|
+
|
74
|
+
# update_status(user)
|
66
75
|
json_scim_response(object: user)
|
67
76
|
end
|
68
77
|
|
69
78
|
private
|
70
79
|
|
71
|
-
|
72
|
-
|
73
|
-
|
80
|
+
def permitted_user_params
|
81
|
+
ScimRails.config.mutable_user_attributes.each.with_object({}) do |attribute, hash|
|
82
|
+
hash[attribute] = find_value_for(attribute)
|
83
|
+
end
|
74
84
|
end
|
75
|
-
end
|
76
85
|
|
77
|
-
|
78
|
-
|
79
|
-
|
86
|
+
def controller_schema
|
87
|
+
ScimRails.config.mutable_user_attributes_schema
|
88
|
+
end
|
80
89
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
90
|
+
def update_status(user)
|
91
|
+
user.public_send(ScimRails.config.user_reprovision_method) if active?
|
92
|
+
user.public_send(ScimRails.config.user_deprovision_method) unless active?
|
93
|
+
end
|
85
94
|
|
86
|
-
|
87
|
-
|
88
|
-
|
95
|
+
def active?
|
96
|
+
active = put_active_param
|
97
|
+
active = patch_active_param if active.nil?
|
98
|
+
|
99
|
+
case active
|
100
|
+
when true, "true", 1
|
101
|
+
true
|
102
|
+
when false, "false", 0
|
103
|
+
false
|
104
|
+
else
|
105
|
+
raise ActiveRecord::RecordInvalid
|
106
|
+
end
|
107
|
+
end
|
89
108
|
|
90
|
-
|
91
|
-
|
92
|
-
true
|
93
|
-
when false, "false", 0
|
94
|
-
false
|
95
|
-
else
|
96
|
-
raise ActiveRecord::RecordInvalid
|
109
|
+
def put_active_param
|
110
|
+
params[:active]
|
97
111
|
end
|
98
|
-
end
|
99
112
|
|
100
|
-
|
101
|
-
|
102
|
-
|
113
|
+
def patch_active_param
|
114
|
+
handle_invalid = lambda do
|
115
|
+
raise ScimRails::ExceptionHandler::UnsupportedPatchRequest
|
116
|
+
end
|
103
117
|
|
104
|
-
|
105
|
-
handle_invalid = lambda do
|
106
|
-
raise ScimRails::ExceptionHandler::UnsupportedPatchRequest
|
107
|
-
end
|
118
|
+
operations = params["Operations"] || {}
|
108
119
|
|
109
|
-
|
120
|
+
valid_operation = operations.find(handle_invalid) do |operation|
|
121
|
+
valid_patch_operation?(operation)
|
122
|
+
end
|
110
123
|
|
111
|
-
|
112
|
-
valid_patch_operation?(operation)
|
124
|
+
valid_operation.dig("value", "active")
|
113
125
|
end
|
114
126
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
operation["value"] &&
|
121
|
-
[true, false].include?(operation["value"]["active"])
|
122
|
-
end
|
127
|
+
def valid_patch_operation?(operation)
|
128
|
+
operation["op"].casecmp("replace") &&
|
129
|
+
operation["value"] &&
|
130
|
+
[true, false].include?(operation["value"]["active"])
|
131
|
+
end
|
123
132
|
end
|
124
133
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Parse PATCH request
|
4
|
+
class ScimPatch
|
5
|
+
attr_accessor :operations
|
6
|
+
|
7
|
+
def initialize(params, mutable_attributes_schema)
|
8
|
+
# FIXME: raise proper error.
|
9
|
+
unless params["schemas"] == ["urn:ietf:params:scim:api:messages:2.0:PatchOp"]
|
10
|
+
raise StandardError
|
11
|
+
end
|
12
|
+
if params["Operations"].nil?
|
13
|
+
raise ScimRails::ExceptionHandler::UnsupportedPatchRequest
|
14
|
+
end
|
15
|
+
|
16
|
+
@operations = params["Operations"].map do |operation|
|
17
|
+
ScimPatchOperation.new(operation["op"], operation["path"], operation["value"],
|
18
|
+
mutable_attributes_schema)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def apply(model)
|
23
|
+
@operations.each do |operation|
|
24
|
+
operation.apply(model)
|
25
|
+
end
|
26
|
+
model
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Parse One of "Operations" in PATCH request
|
4
|
+
class ScimPatchOperation
|
5
|
+
attr_accessor :op, :path_scim, :path_sp, :value
|
6
|
+
|
7
|
+
def initialize(op, path, value, mutable_attributes_schema)
|
8
|
+
# FIXME: Raise proper Error
|
9
|
+
raise StandardError unless op.downcase.in? %w[add replace remove]
|
10
|
+
|
11
|
+
# No path is not supported.
|
12
|
+
# FIXME: Raise proper Error
|
13
|
+
raise ScimRails::ExceptionHandler::UnsupportedPatchRequest if path.nil?
|
14
|
+
raise ScimRails::ExceptionHandler::UnsupportedPatchRequest if value.nil?
|
15
|
+
|
16
|
+
@op = op.downcase.to_sym
|
17
|
+
@path_scim = path
|
18
|
+
@path_sp = convert_path(path, mutable_attributes_schema)
|
19
|
+
@value = value
|
20
|
+
end
|
21
|
+
|
22
|
+
# WIP
|
23
|
+
def apply(model)
|
24
|
+
case @op
|
25
|
+
when :add
|
26
|
+
model.attributes = { @path_sp => @value }
|
27
|
+
when :replace
|
28
|
+
model.attributes = { @path_sp => @value }
|
29
|
+
when :remove
|
30
|
+
model.attributes = { @path_sp => nil }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def convert_path(path, mutable_attributes_schema)
|
37
|
+
# For now, library does not support Multi-Valued Attributes properly.
|
38
|
+
# examle:
|
39
|
+
# path = 'emails[type eq "work"].value'
|
40
|
+
# mutable_attributes_schema = {
|
41
|
+
# emails: [
|
42
|
+
# {
|
43
|
+
# value: :mail_address,
|
44
|
+
# }
|
45
|
+
# ],
|
46
|
+
# }
|
47
|
+
#
|
48
|
+
# Library ignores filter conditions (like [type eq "work"])
|
49
|
+
# and always uses the first element of the array
|
50
|
+
dig_keys = path.gsub(/\[(.+?)\]/, ".0").split(".").map do |step|
|
51
|
+
step == "0" ? 0 : step.to_sym
|
52
|
+
end
|
53
|
+
mutable_attributes_schema.dig(*dig_keys)
|
54
|
+
end
|
55
|
+
end
|
data/lib/scim_rails/version.rb
CHANGED
@@ -532,7 +532,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
532
532
|
expect(response.status).to eq 404
|
533
533
|
end
|
534
534
|
|
535
|
-
|
535
|
+
xit "successfully archives user" do
|
536
536
|
expect(company.users.count).to eq 1
|
537
537
|
user = company.users.first
|
538
538
|
expect(user.archived?).to eq false
|
@@ -545,7 +545,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
545
545
|
expect(user.archived?).to eq true
|
546
546
|
end
|
547
547
|
|
548
|
-
|
548
|
+
xit "successfully restores user" do
|
549
549
|
expect(company.users.count).to eq 1
|
550
550
|
user = company.users.first.tap(&:archive!)
|
551
551
|
expect(user.archived?).to eq true
|
@@ -561,17 +561,34 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
561
561
|
expect(user.archived?).to eq false
|
562
562
|
end
|
563
563
|
|
564
|
+
it "successfully change user email" do
|
565
|
+
expect(company.users.count).to eq 1
|
566
|
+
user = company.users.first
|
567
|
+
user.update(email: 'test@example.com')
|
568
|
+
expect(user.reload.email).to eq 'test@example.com'
|
569
|
+
|
570
|
+
patch \
|
571
|
+
:patch_update,
|
572
|
+
params: patch_params(id: 1, active: true),
|
573
|
+
as: :json
|
574
|
+
|
575
|
+
expect(response.status).to eq 200
|
576
|
+
expect(company.users.count).to eq 1
|
577
|
+
user.reload
|
578
|
+
expect(user.email).to eq 'change@example.com'
|
579
|
+
end
|
580
|
+
|
564
581
|
it "is case insensetive for op value" do
|
565
582
|
# Note, this is for backward compatibility. op should always
|
566
583
|
# be lower case and support for case insensitivity will be removed
|
567
584
|
patch :patch_update, params: {
|
585
|
+
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
|
568
586
|
id: 1,
|
569
587
|
Operations: [
|
570
|
-
|
588
|
+
{
|
571
589
|
op: "Replace",
|
572
|
-
|
573
|
-
|
574
|
-
}
|
590
|
+
path: "emails[type eq \"work\"].value",
|
591
|
+
value: "test@example.com"
|
575
592
|
}
|
576
593
|
]
|
577
594
|
}, as: :json
|
@@ -579,45 +596,44 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
579
596
|
expect(response.status).to eq 200
|
580
597
|
end
|
581
598
|
|
582
|
-
|
599
|
+
xit "returns 422 when value is not an object" do
|
583
600
|
patch :patch_update, params: {
|
601
|
+
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
|
584
602
|
id: 1,
|
585
603
|
Operations: [
|
586
604
|
{
|
587
605
|
op: "replace",
|
588
|
-
|
589
|
-
|
590
|
-
givenName: "Francis"
|
591
|
-
}
|
592
|
-
}
|
606
|
+
path: "emails[type eq \"work\"].value",
|
607
|
+
value: "francis@example.com"
|
593
608
|
}
|
594
609
|
]
|
595
|
-
}
|
610
|
+
}
|
596
611
|
|
597
612
|
expect(response.status).to eq 422
|
598
613
|
response_body = JSON.parse(response.body)
|
599
614
|
expect(response_body.dig("schemas", 0)).to eq "urn:ietf:params:scim:api:messages:2.0:Error"
|
600
615
|
end
|
601
616
|
|
602
|
-
it "returns 422 when value is
|
617
|
+
it "returns 422 when value is missing" do
|
603
618
|
patch :patch_update, params: {
|
619
|
+
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
|
604
620
|
id: 1,
|
605
621
|
Operations: [
|
606
622
|
{
|
607
623
|
op: "replace",
|
608
|
-
path: "
|
609
|
-
value: "Francis"
|
624
|
+
path: "emails[type eq \"work\"].value"
|
610
625
|
}
|
611
626
|
]
|
612
|
-
}
|
627
|
+
}, as: :json
|
613
628
|
|
614
629
|
expect(response.status).to eq 422
|
615
630
|
response_body = JSON.parse(response.body)
|
616
631
|
expect(response_body.dig("schemas", 0)).to eq "urn:ietf:params:scim:api:messages:2.0:Error"
|
617
632
|
end
|
618
633
|
|
619
|
-
it "returns 422 when
|
634
|
+
it "returns 422 when path is missing" do
|
620
635
|
patch :patch_update, params: {
|
636
|
+
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
|
621
637
|
id: 1,
|
622
638
|
Operations: [
|
623
639
|
{
|
@@ -633,6 +649,7 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
633
649
|
|
634
650
|
it "returns 422 operations key is missing" do
|
635
651
|
patch :patch_update, params: {
|
652
|
+
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
|
636
653
|
id: 1,
|
637
654
|
Foobars: [
|
638
655
|
{
|
@@ -650,13 +667,13 @@ RSpec.describe ScimRails::ScimUsersController, type: :controller do
|
|
650
667
|
|
651
668
|
def patch_params(id:, active: false)
|
652
669
|
{
|
670
|
+
schemas: ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
|
653
671
|
id: id,
|
654
672
|
Operations: [
|
655
673
|
{
|
656
|
-
op: "
|
657
|
-
|
658
|
-
|
659
|
-
}
|
674
|
+
op: "Replace",
|
675
|
+
path: "emails[type eq \"work\"].value",
|
676
|
+
value: "change@example.com"
|
660
677
|
}
|
661
678
|
]
|
662
679
|
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe ScimPatchOperation do
|
6
|
+
|
7
|
+
let(:op) { 'Replace' }
|
8
|
+
let(:path) { 'userName' }
|
9
|
+
let(:value) { 'taro.suzuki' }
|
10
|
+
let(:mutable_attributes_schema) {
|
11
|
+
{
|
12
|
+
userName: :name,
|
13
|
+
displayName: :display_name,
|
14
|
+
emails: [
|
15
|
+
{
|
16
|
+
value: :email
|
17
|
+
}
|
18
|
+
],
|
19
|
+
name: {
|
20
|
+
familyName: :family_name,
|
21
|
+
givenName: :given_name
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
let(:operation) {
|
26
|
+
described_class.new(
|
27
|
+
op,
|
28
|
+
path,
|
29
|
+
value,
|
30
|
+
mutable_attributes_schema
|
31
|
+
)
|
32
|
+
}
|
33
|
+
describe '#initialize' do
|
34
|
+
context 'replace single attribute' do
|
35
|
+
it {
|
36
|
+
expect(operation.op).to eq :replace
|
37
|
+
expect(operation.path_scim).to eq path
|
38
|
+
expect(operation.path_sp).to eq :name
|
39
|
+
expect(operation.value).to eq value
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'add single attribute' do
|
44
|
+
let(:op) { 'Add' }
|
45
|
+
it {
|
46
|
+
expect(operation.op).to eq :add
|
47
|
+
expect(operation.path_scim).to eq path
|
48
|
+
expect(operation.path_sp).to eq :name
|
49
|
+
expect(operation.value).to eq value
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'remove single attribute' do
|
54
|
+
let(:op) { 'Remove' }
|
55
|
+
it {
|
56
|
+
expect(operation.op).to eq :remove
|
57
|
+
expect(operation.path_scim).to eq path
|
58
|
+
expect(operation.path_sp).to eq :name
|
59
|
+
expect(operation.value).to eq value
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'replace email address' do
|
64
|
+
let(:path) { 'emails[type eq "work"].value' }
|
65
|
+
let(:value) { 'taro.suzuki@example.com' }
|
66
|
+
it {
|
67
|
+
expect(operation.op).to eq :replace
|
68
|
+
expect(operation.path_scim).to eq path
|
69
|
+
expect(operation.path_sp).to eq :email
|
70
|
+
expect(operation.value).to eq value
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'replace name.familyName' do
|
75
|
+
let(:path) { 'name.familyName' }
|
76
|
+
let(:value) { 'Suzuki' }
|
77
|
+
it {
|
78
|
+
expect(operation.op).to eq :replace
|
79
|
+
expect(operation.path_scim).to eq path
|
80
|
+
expect(operation.path_sp).to eq :family_name
|
81
|
+
expect(operation.value).to eq value
|
82
|
+
}
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe ScimPatch do
|
6
|
+
|
7
|
+
let(:params) {
|
8
|
+
{
|
9
|
+
'schemas' => ['urn:ietf:params:scim:api:messages:2.0:PatchOp'],
|
10
|
+
'Operations' => [
|
11
|
+
{
|
12
|
+
'op' => 'Replace',
|
13
|
+
'path' => 'userName',
|
14
|
+
'value' => 'taro.suzuki'
|
15
|
+
},
|
16
|
+
{
|
17
|
+
'op' => 'Replace',
|
18
|
+
'path' => 'emails[type eq "work"].value',
|
19
|
+
'value' => 'taro.suzuki@example.com'
|
20
|
+
},
|
21
|
+
{
|
22
|
+
'op' => 'Replace',
|
23
|
+
'path' => 'name.familyName',
|
24
|
+
'value' => 'Suzuki'
|
25
|
+
}
|
26
|
+
]
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
let(:mutable_attributes_schema) {
|
31
|
+
{
|
32
|
+
userName: :name,
|
33
|
+
displayName: :display_name,
|
34
|
+
emails: [
|
35
|
+
{
|
36
|
+
value: :email
|
37
|
+
}
|
38
|
+
],
|
39
|
+
name: {
|
40
|
+
familyName: :family_name,
|
41
|
+
givenName: :given_name
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
let(:patch) { described_class.new(params, mutable_attributes_schema) }
|
47
|
+
|
48
|
+
describe '#initialize' do
|
49
|
+
it {
|
50
|
+
expect(patch.operations[0].op).to eq :replace
|
51
|
+
expect(patch.operations[0].path_scim).to eq 'userName'
|
52
|
+
expect(patch.operations[0].path_sp).to eq :name
|
53
|
+
expect(patch.operations[0].value).to eq 'taro.suzuki'
|
54
|
+
|
55
|
+
expect(patch.operations[1].op).to eq :replace
|
56
|
+
expect(patch.operations[1].path_scim).to eq 'emails[type eq "work"].value'
|
57
|
+
expect(patch.operations[1].path_sp).to eq :email
|
58
|
+
expect(patch.operations[1].value).to eq 'taro.suzuki@example.com'
|
59
|
+
|
60
|
+
expect(patch.operations[2].op).to eq :replace
|
61
|
+
expect(patch.operations[2].path_scim).to eq 'name.familyName'
|
62
|
+
expect(patch.operations[2].path_sp).to eq :family_name
|
63
|
+
expect(patch.operations[2].value).to eq 'Suzuki'
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
# describe '#update' do
|
68
|
+
# create user by factory bot
|
69
|
+
# patch.update(user)
|
70
|
+
# end
|
71
|
+
|
72
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scimaenaga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Studist Corporation
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -149,6 +149,8 @@ files:
|
|
149
149
|
- app/controllers/scim_rails/scim_groups_controller.rb
|
150
150
|
- app/controllers/scim_rails/scim_users_controller.rb
|
151
151
|
- app/helpers/scim_rails/application_helper.rb
|
152
|
+
- app/libraries/scim_patch.rb
|
153
|
+
- app/libraries/scim_patch_operation.rb
|
152
154
|
- app/models/scim_rails/application_record.rb
|
153
155
|
- app/models/scim_rails/authorize_api_request.rb
|
154
156
|
- app/models/scim_rails/scim_count.rb
|
@@ -233,11 +235,13 @@ files:
|
|
233
235
|
- spec/factories/group.rb
|
234
236
|
- spec/factories/user.rb
|
235
237
|
- spec/lib/scim_rails/encoder_spec.rb
|
238
|
+
- spec/libraries/scim_patch_operation_spec.rb
|
239
|
+
- spec/libraries/scim_patch_spec.rb
|
236
240
|
- spec/spec_helper.rb
|
237
241
|
- spec/support/auth_helper.rb
|
238
242
|
- spec/support/factory_bot.rb
|
239
243
|
- spec/support/scim_rails_config.rb
|
240
|
-
homepage: https://github.com/StudistCorporation/
|
244
|
+
homepage: https://github.com/StudistCorporation/scimaenaga
|
241
245
|
licenses:
|
242
246
|
- MIT
|
243
247
|
metadata: {}
|
@@ -333,6 +337,8 @@ test_files:
|
|
333
337
|
- spec/controllers/scim_rails/scim_users_request_spec.rb
|
334
338
|
- spec/controllers/scim_rails/scim_groups_request_spec.rb
|
335
339
|
- spec/controllers/scim_rails/scim_groups_controller_spec.rb
|
340
|
+
- spec/libraries/scim_patch_spec.rb
|
341
|
+
- spec/libraries/scim_patch_operation_spec.rb
|
336
342
|
- spec/factories/user.rb
|
337
343
|
- spec/factories/group.rb
|
338
344
|
- spec/factories/company.rb
|