scim_users_controller.rb
3.95 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
125
126
127
128
129
130
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
username_key = ScimRails.config.queryable_user_attributes[:userName]
find_by_username = Hash.new
find_by_username[username_key] = permitted_user_params[username_key]
user = @company
.public_send(ScimRails.config.scim_users_scope)
.find_or_create_by(find_by_username)
user.update!(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