scim_users_controller.rb
3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
module ScimRails
class ScimUsersController < ScimRails::ApplicationController
def index
if params[:filter].present?
query = ScimRails::ScimQueryParser.new(params[:filter])
users = @company
.public_send(ScimRails.config.scim_users_scope)
.where(
"#{ScimRails.config.scim_users_model.connection.quote_column_name(query.attribute)} #{query.operator} ?",
query.parameter
)
.order(ScimRails.config.scim_users_list_order)
else
users = @company
.public_send(ScimRails.config.scim_users_scope)
.order(ScimRails.config.scim_users_list_order)
end
counts = ScimCount.new(
start_index: params[:startIndex],
limit: params[:count],
total: users.count
)
json_scim_response(object: users, counts: counts)
end
def create
user = @company.public_send(ScimRails.config.scim_users_scope).create!(permitted_user_params)
update_status(user) unless put_active_param.nil?
json_scim_response(object: user, status: :created)
end
def show
user = @company.public_send(ScimRails.config.scim_users_scope).find(params[:id])
json_scim_response(object: user)
end
def put_update
user = @company.public_send(ScimRails.config.scim_users_scope).find(params[:id])
update_status(user) unless put_active_param.nil?
user.update!(permitted_user_params)
json_scim_response(object: user)
end
# TODO: PATCH will only deprovision or reprovision users.
# This will work just fine for Okta but is not SCIM compliant.
def patch_update
user = @company.public_send(ScimRails.config.scim_users_scope).find(params[:id])
update_status(user)
json_scim_response(object: user)
end
private
def permitted_user_params
ScimRails.config.mutable_user_attributes.each.with_object({}) do |attribute, hash|
hash[attribute] = find_value_for(attribute)
end
end
def find_value_for(attribute)
params.dig(*path_for(attribute))
end
# `path_for` is a recursive method used to find the "path" for
# `.dig` to take when looking for a given attribute in the
# params.
#
# Example: `path_for(:name)` should return an array that looks
# like [:names, 0, :givenName]. `.dig` can then use that path
# against the params to translate the :name attribute to "John".
def path_for(attribute, object = ScimRails.config.mutable_user_attributes_schema, path = [])
at_path = path.empty? ? object : object.dig(*path)
return path if at_path == attribute
case at_path
when Hash
at_path.each do |key, value|
found_path = path_for(attribute, object, [*path, key])
return found_path if found_path
end
nil
when Array
at_path.each_with_index do |value, index|
found_path = path_for(attribute, object, [*path, index])
return found_path if found_path
end
nil
end
end
def update_status(user)
user.public_send(ScimRails.config.user_reprovision_method) if active?
user.public_send(ScimRails.config.user_deprovision_method) unless active?
end
def active?
active = put_active_param
active = patch_active_param if active.nil?
case active
when true, "true", 1
true
when false, "false", 0
false
else
raise ActiveRecord::RecordInvalid
end
end
def put_active_param
params[:active]
end
def patch_active_param
active = params.dig("Operations", 0, "value", "active")
raise ScimRails::ExceptionHandler::UnsupportedPatchRequest if active.nil?
active
end
end
end