descope 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/workflows/ci.yaml +54 -0
- data/.gitignore +59 -0
- data/.release-please-manifest.json +3 -0
- data/.rubocop.yml +10 -0
- data/.rubocop_todo.yml +10 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +90 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +204 -0
- data/LICENSE +21 -0
- data/README.md +1171 -0
- data/Rakefile +31 -0
- data/descope.gemspec +34 -0
- data/examples/ruby/Gemfile +4 -0
- data/examples/ruby/Gemfile.lock +41 -0
- data/examples/ruby/access_key_app.rb +45 -0
- data/examples/ruby/enchantedlink_app.rb +65 -0
- data/examples/ruby/magiclink_app.rb +81 -0
- data/examples/ruby/management/Gemfile +5 -0
- data/examples/ruby/management/Gemfile.lock +38 -0
- data/examples/ruby/management/access_key_app.rb +71 -0
- data/examples/ruby/management/audit_app.rb +25 -0
- data/examples/ruby/management/authz_app.rb +135 -0
- data/examples/ruby/management/authz_files.json +229 -0
- data/examples/ruby/management/flow_app.rb +57 -0
- data/examples/ruby/management/permission_app.rb +56 -0
- data/examples/ruby/management/role_app.rb +58 -0
- data/examples/ruby/management/tenant_app.rb +60 -0
- data/examples/ruby/management/user_app.rb +60 -0
- data/examples/ruby/oauth_app.rb +39 -0
- data/examples/ruby/otp_app.rb +50 -0
- data/examples/ruby/password_app.rb +76 -0
- data/examples/ruby/saml_app.rb +38 -0
- data/examples/ruby-on-rails-api/descope/.dockerignore +37 -0
- data/examples/ruby-on-rails-api/descope/.gitattributes +9 -0
- data/examples/ruby-on-rails-api/descope/.gitignore +40 -0
- data/examples/ruby-on-rails-api/descope/.node-version +1 -0
- data/examples/ruby-on-rails-api/descope/.ruby-version +1 -0
- data/examples/ruby-on-rails-api/descope/Dockerfile +75 -0
- data/examples/ruby-on-rails-api/descope/Gemfile +67 -0
- data/examples/ruby-on-rails-api/descope/Gemfile.lock +284 -0
- data/examples/ruby-on-rails-api/descope/Procfile.dev +3 -0
- data/examples/ruby-on-rails-api/descope/README.md +54 -0
- data/examples/ruby-on-rails-api/descope/Rakefile +6 -0
- data/examples/ruby-on-rails-api/descope/app/assets/builds/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/config/manifest.js +3 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/descope.jpeg +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/favicon.ico +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/logo192.png +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/images/logo512.png +0 -0
- data/examples/ruby-on-rails-api/descope/app/assets/stylesheets/application.bootstrap.scss +67 -0
- data/examples/ruby-on-rails-api/descope/app/channels/application_cable/channel.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/channels/application_cable/connection.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/application_controller.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/concerns/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/homepage_controller.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/controllers/session_controller.rb +66 -0
- data/examples/ruby-on-rails-api/descope/app/helpers/application_helper.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/helpers/homepage_helper.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/helpers/session_helper.rb +2 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/App.css +53 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/application.js +5 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/App.jsx +4 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Dashboard.jsx +60 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Home.jsx +27 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Login.jsx +45 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/Profile.jsx +81 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/index.html +11 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/components/index.jsx +24 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/controllers/application.js +9 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/controllers/index.js +5 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/reportWebVitals.js +13 -0
- data/examples/ruby-on-rails-api/descope/app/javascript/routes/index.jsx +17 -0
- data/examples/ruby-on-rails-api/descope/app/jobs/application_job.rb +7 -0
- data/examples/ruby-on-rails-api/descope/app/mailers/application_mailer.rb +4 -0
- data/examples/ruby-on-rails-api/descope/app/models/application_record.rb +3 -0
- data/examples/ruby-on-rails-api/descope/app/models/concerns/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/app/views/homepage/index.html.erb +2 -0
- data/examples/ruby-on-rails-api/descope/app/views/layouts/application.html.erb +16 -0
- data/examples/ruby-on-rails-api/descope/app/views/layouts/mailer.html.erb +13 -0
- data/examples/ruby-on-rails-api/descope/app/views/layouts/mailer.text.erb +1 -0
- data/examples/ruby-on-rails-api/descope/app/views/session/index.html.erb +2 -0
- data/examples/ruby-on-rails-api/descope/bin/bundle +109 -0
- data/examples/ruby-on-rails-api/descope/bin/dev +11 -0
- data/examples/ruby-on-rails-api/descope/bin/docker-entrypoint +8 -0
- data/examples/ruby-on-rails-api/descope/bin/rails +4 -0
- data/examples/ruby-on-rails-api/descope/bin/rake +4 -0
- data/examples/ruby-on-rails-api/descope/bin/setup +36 -0
- data/examples/ruby-on-rails-api/descope/build.js +30 -0
- data/examples/ruby-on-rails-api/descope/config/application.rb +42 -0
- data/examples/ruby-on-rails-api/descope/config/boot.rb +4 -0
- data/examples/ruby-on-rails-api/descope/config/cable.yml +10 -0
- data/examples/ruby-on-rails-api/descope/config/config.yml +9 -0
- data/examples/ruby-on-rails-api/descope/config/credentials.yml.enc +1 -0
- data/examples/ruby-on-rails-api/descope/config/database.yml +25 -0
- data/examples/ruby-on-rails-api/descope/config/environment.rb +5 -0
- data/examples/ruby-on-rails-api/descope/config/environments/development.rb +76 -0
- data/examples/ruby-on-rails-api/descope/config/environments/production.rb +97 -0
- data/examples/ruby-on-rails-api/descope/config/environments/test.rb +64 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/assets.rb +13 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/content_security_policy.rb +25 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/inflections.rb +16 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/load_config.rb +12 -0
- data/examples/ruby-on-rails-api/descope/config/initializers/permissions_policy.rb +13 -0
- data/examples/ruby-on-rails-api/descope/config/locales/en.yml +31 -0
- data/examples/ruby-on-rails-api/descope/config/puma.rb +35 -0
- data/examples/ruby-on-rails-api/descope/config/routes.rb +18 -0
- data/examples/ruby-on-rails-api/descope/config/storage.yml +34 -0
- data/examples/ruby-on-rails-api/descope/config.ru +6 -0
- data/examples/ruby-on-rails-api/descope/db/seeds.rb +9 -0
- data/examples/ruby-on-rails-api/descope/lib/assets/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/lib/tasks/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/log/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/package-lock.json +19680 -0
- data/examples/ruby-on-rails-api/descope/package.json +51 -0
- data/examples/ruby-on-rails-api/descope/public/404.html +67 -0
- data/examples/ruby-on-rails-api/descope/public/422.html +67 -0
- data/examples/ruby-on-rails-api/descope/public/500.html +66 -0
- data/examples/ruby-on-rails-api/descope/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/ruby-on-rails-api/descope/public/apple-touch-icon.png +0 -0
- data/examples/ruby-on-rails-api/descope/public/favicon.ico +0 -0
- data/examples/ruby-on-rails-api/descope/public/robots.txt +1 -0
- data/examples/ruby-on-rails-api/descope/storage/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/tmp/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/tmp/pids/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/tmp/storage/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/vendor/.keep +0 -0
- data/examples/ruby-on-rails-api/descope/yarn.lock +10780 -0
- data/lib/descope/api/v1/auth/enchantedlink.rb +156 -0
- data/lib/descope/api/v1/auth/magiclink.rb +170 -0
- data/lib/descope/api/v1/auth/oauth.rb +72 -0
- data/lib/descope/api/v1/auth/otp.rb +186 -0
- data/lib/descope/api/v1/auth/password.rb +100 -0
- data/lib/descope/api/v1/auth/saml.rb +48 -0
- data/lib/descope/api/v1/auth/totp.rb +72 -0
- data/lib/descope/api/v1/auth.rb +452 -0
- data/lib/descope/api/v1/management/access_key.rb +81 -0
- data/lib/descope/api/v1/management/audit.rb +82 -0
- data/lib/descope/api/v1/management/authz.rb +165 -0
- data/lib/descope/api/v1/management/common.rb +147 -0
- data/lib/descope/api/v1/management/flow.rb +55 -0
- data/lib/descope/api/v1/management/password.rb +58 -0
- data/lib/descope/api/v1/management/permission.rb +48 -0
- data/lib/descope/api/v1/management/project.rb +53 -0
- data/lib/descope/api/v1/management/role.rb +48 -0
- data/lib/descope/api/v1/management/scim.rb +206 -0
- data/lib/descope/api/v1/management/sso_settings.rb +153 -0
- data/lib/descope/api/v1/management/tenant.rb +71 -0
- data/lib/descope/api/v1/management/user.rb +619 -0
- data/lib/descope/api/v1/management.rb +38 -0
- data/lib/descope/api/v1/session.rb +84 -0
- data/lib/descope/api/v1.rb +13 -0
- data/lib/descope/client.rb +6 -0
- data/lib/descope/exception.rb +50 -0
- data/lib/descope/mixins/common.rb +129 -0
- data/lib/descope/mixins/headers.rb +15 -0
- data/lib/descope/mixins/http.rb +133 -0
- data/lib/descope/mixins/initializer.rb +80 -0
- data/lib/descope/mixins/logging.rb +30 -0
- data/lib/descope/mixins/validation.rb +79 -0
- data/lib/descope/mixins.rb +22 -0
- data/lib/descope/version.rb +7 -0
- data/lib/descope.rb +9 -0
- data/lib/descope_client.rb +5 -0
- data/release-please-config.json +18 -0
- data/renovate.json +6 -0
- data/spec/factories/user.rb +16 -0
- data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +159 -0
- data/spec/lib.descope/api/v1/auth/magiclink_spec.rb +282 -0
- data/spec/lib.descope/api/v1/auth/oauth_spec.rb +117 -0
- data/spec/lib.descope/api/v1/auth/otp_spec.rb +285 -0
- data/spec/lib.descope/api/v1/auth/password_spec.rb +124 -0
- data/spec/lib.descope/api/v1/auth/saml_spec.rb +55 -0
- data/spec/lib.descope/api/v1/auth/totp_spec.rb +70 -0
- data/spec/lib.descope/api/v1/auth_spec.rb +372 -0
- data/spec/lib.descope/api/v1/management/access_key_spec.rb +118 -0
- data/spec/lib.descope/api/v1/management/audit_spec.rb +78 -0
- data/spec/lib.descope/api/v1/management/authz_spec.rb +336 -0
- data/spec/lib.descope/api/v1/management/flow_spec.rb +78 -0
- data/spec/lib.descope/api/v1/management/password_spec.rb +25 -0
- data/spec/lib.descope/api/v1/management/permission_spec.rb +81 -0
- data/spec/lib.descope/api/v1/management/project_spec.rb +63 -0
- data/spec/lib.descope/api/v1/management/role_spec.rb +85 -0
- data/spec/lib.descope/api/v1/management/scim_spec.rb +312 -0
- data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +172 -0
- data/spec/lib.descope/api/v1/management/tenant_spec.rb +141 -0
- data/spec/lib.descope/api/v1/management/user_spec.rb +667 -0
- data/spec/lib.descope/api/v1/session_spec.rb +117 -0
- data/spec/lib.descope/client_spec.rb +40 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/client_config.rb +14 -0
- data/spec/support/dummy_class.rb +36 -0
- data/spec/support/utils.rb +32 -0
- metadata +420 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Descope
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
module Management
|
7
|
+
# Management API calls
|
8
|
+
module SCIM
|
9
|
+
include Descope::Api::V1::Management::Common
|
10
|
+
|
11
|
+
def scim_search_groups(filter: nil, start_index: nil, count: nil, excluded_attributes: nil)
|
12
|
+
# Search SCIM Groups
|
13
|
+
url = compose_scim_search_groups_url(filter, start_index, count, excluded_attributes)
|
14
|
+
get(url)
|
15
|
+
end
|
16
|
+
|
17
|
+
def scim_create_group(group_id: nil, display_name: nil, members: nil, external_id: nil,
|
18
|
+
excluded_attributes: nil)
|
19
|
+
# Create SCIM Group
|
20
|
+
body = compose_scim_create_group_body(group_id, display_name, members, external_id, excluded_attributes)
|
21
|
+
post(SCIM_GROUPS_PATH, body)
|
22
|
+
end
|
23
|
+
|
24
|
+
def scim_load_group(group_id: nil, display_name: nil, external_id: nil, excluded_attributes: nil)
|
25
|
+
# Load SCIM Group, using a valid access key.
|
26
|
+
validate_scim_group_id(group_id)
|
27
|
+
url = compose_scim_create_group_url(group_id, display_name, external_id, excluded_attributes)
|
28
|
+
get(url)
|
29
|
+
end
|
30
|
+
|
31
|
+
def scim_update_group(group_id: nil, display_name: nil, members: nil, external_id: nil,
|
32
|
+
excluded_attributes: nil)
|
33
|
+
# Update SCIM Group, using a valid access key.
|
34
|
+
validate_scim_group_id(group_id)
|
35
|
+
body = compose_scim_update_group_body(group_id, display_name, members, external_id, excluded_attributes)
|
36
|
+
patch("#{SCIM_GROUPS_PATH}/#{group_id}", body)
|
37
|
+
end
|
38
|
+
|
39
|
+
def scim_delete_group(group_id)
|
40
|
+
# Delete SCIM Group, using a valid access key.
|
41
|
+
validate_scim_group_id(group_id)
|
42
|
+
url = "#{SCIM_GROUPS_PATH}/#{group_id}"
|
43
|
+
delete(url)
|
44
|
+
end
|
45
|
+
|
46
|
+
def scim_patch_group(group_id: nil, user_id: nil, operations: nil)
|
47
|
+
# Patch SCIM Group, using a valid access key.
|
48
|
+
validate_scim_group_id(group_id)
|
49
|
+
url = compose_scim_patch_group_url(group_id, user_id, operations)
|
50
|
+
patch(url)
|
51
|
+
end
|
52
|
+
|
53
|
+
# SCIM Users
|
54
|
+
def scim_load_resource_types
|
55
|
+
# Load SCIM Resource Types, using a valid access key.
|
56
|
+
get(SCIM_RESOURCE_TYPES_PATH)
|
57
|
+
end
|
58
|
+
|
59
|
+
def scim_load_service_provider_config
|
60
|
+
# Load SCIM Service Provider Config, using a valid access key.
|
61
|
+
get(SCIM_SERVICE_PROVIDER_CONFIG_PATH)
|
62
|
+
end
|
63
|
+
|
64
|
+
def scim_search_users(filter: nil, start_index: nil, count: nil)
|
65
|
+
# Search SCIM Users, using a valid access key.
|
66
|
+
url = compose_scim_search_users_url(filter, start_index, count)
|
67
|
+
get(url)
|
68
|
+
end
|
69
|
+
|
70
|
+
def scim_create_user(user_id: nil, display_name: nil, emails: nil,
|
71
|
+
phone_numbers: nil, active: nil, name: nil, user_name: nil)
|
72
|
+
# Create SCIM User, using a valid access key.
|
73
|
+
validate_user_id(user_id)
|
74
|
+
body = compose_scim_create_user_body(user_id, display_name, emails, phone_numbers, active, name, user_name)
|
75
|
+
post(SCIM_USERS_PATH, body)
|
76
|
+
end
|
77
|
+
|
78
|
+
def scim_load_user(user_id)
|
79
|
+
# Load SCIM User, using a valid access key.
|
80
|
+
validate_user_id(user_id)
|
81
|
+
url = "#{SCIM_USERS_PATH}/#{user_id}"
|
82
|
+
get(url)
|
83
|
+
end
|
84
|
+
|
85
|
+
def scim_update_user(user_id)
|
86
|
+
# Update SCIM User, using a valid access key.
|
87
|
+
validate_user_id(user_id)
|
88
|
+
url = "#{SCIM_USERS_PATH}/#{user_id}"
|
89
|
+
patch(url)
|
90
|
+
end
|
91
|
+
|
92
|
+
def scim_delete_user(user_id)
|
93
|
+
# Delete SCIM User, using a valid access key.
|
94
|
+
validate_user_id(user_id)
|
95
|
+
url = "#{SCIM_USERS_PATH}/#{user_id}"
|
96
|
+
delete(url)
|
97
|
+
end
|
98
|
+
|
99
|
+
def scim_patch_user(user_id: nil, group_id: nil, operations: nil)
|
100
|
+
# Patch SCIM User, using a valid access key.
|
101
|
+
validate_user_id(user_id)
|
102
|
+
validate_scim_group_id(group_id)
|
103
|
+
body = compose_scim_patch_user_body(user_id, group_id, operations)
|
104
|
+
patch(SCIM_USERS_PATH, body)
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def compose_scim_search_groups_url(filter, start_index, count, excluded_attributes)
|
110
|
+
url = "#{SCIM_GROUPS_PATH}?"
|
111
|
+
url += "filter=#{filter}&" unless filter.nil?
|
112
|
+
url += "startIndex=#{start_index}&" unless start_index.nil?
|
113
|
+
url += "count=#{count}&" unless count.nil?
|
114
|
+
url += "excludedAttributes=#{excluded_attributes}&" unless excluded_attributes.nil?
|
115
|
+
url
|
116
|
+
end
|
117
|
+
|
118
|
+
def compose_scim_create_group_body(group_id, display_name, members, external_id, excluded_attributes)
|
119
|
+
body = {}
|
120
|
+
body['id'] = group_id unless group_id.nil?
|
121
|
+
body['displayName'] = display_name unless display_name.nil?
|
122
|
+
body['members'] = members unless members.nil?
|
123
|
+
body['externalId'] = external_id unless external_id.nil?
|
124
|
+
body['excludedAttributes'] = excluded_attributes unless excluded_attributes.nil?
|
125
|
+
body
|
126
|
+
end
|
127
|
+
|
128
|
+
def compose_scim_create_group_url(group_id, display_name, external_id, excluded_attributes)
|
129
|
+
display_name = CGI.escape(display_name) unless display_name.nil?
|
130
|
+
url = "#{SCIM_GROUPS_PATH}/#{group_id}?"
|
131
|
+
url += "displayName=#{display_name}&" unless display_name.nil?
|
132
|
+
url += "externalId=#{external_id}&" unless external_id.nil?
|
133
|
+
url += "excludedAttributes=#{excluded_attributes}" unless excluded_attributes.nil?
|
134
|
+
url
|
135
|
+
end
|
136
|
+
|
137
|
+
def compose_scim_update_group_body(group_id, display_name, members, external_id, excluded_attributes)
|
138
|
+
body = {}
|
139
|
+
body[:groupId] = group_id unless group_id.nil?
|
140
|
+
body[:displayName] = display_name unless display_name.nil?
|
141
|
+
body[:members] = members unless members.nil?
|
142
|
+
body[:externalId] = external_id unless external_id.nil?
|
143
|
+
body[:excludedAttributes] = excluded_attributes unless excluded_attributes.nil?
|
144
|
+
body
|
145
|
+
end
|
146
|
+
|
147
|
+
def compose_scim_patch_group_url(group_id, user_id, operations)
|
148
|
+
url = "#{SCIM_GROUPS_PATH}/#{group_id}&"
|
149
|
+
url += "userId=#{user_id}&" unless user_id.nil?
|
150
|
+
url += "operations=#{compose_operations_param(operations)}&" unless operations.nil?
|
151
|
+
url
|
152
|
+
end
|
153
|
+
|
154
|
+
def compose_scim_search_users_url(filter, start_index, count)
|
155
|
+
url = "#{SCIM_USERS_PATH}?"
|
156
|
+
url += "filter=#{filter}&" unless filter.nil?
|
157
|
+
url += "startIndex=#{start_index}&" unless start_index.nil?
|
158
|
+
url += "count=#{count}&" unless count.nil?
|
159
|
+
url
|
160
|
+
end
|
161
|
+
|
162
|
+
def compose_scim_create_user_body(user_id, display_name, emails, phone_numbers, active, name, user_name)
|
163
|
+
raise AuthException.new('name must be a hash of these fields: given_name, family_name, last_name') if !name.nil? && !name.is_a?(Hash)
|
164
|
+
|
165
|
+
body = {}
|
166
|
+
body[:userId] = user_id unless user_id.nil?
|
167
|
+
body[:displayName] = display_name unless display_name.nil?
|
168
|
+
body[:emails] = emails unless emails.nil?
|
169
|
+
body[:phoneNumbers] = phone_numbers unless phone_numbers.nil?
|
170
|
+
body[:active] = active unless active.nil?
|
171
|
+
body[:name] = {} unless name.nil?
|
172
|
+
body[:name][:givenName] = name[:given_name] unless name[:given_name].nil?
|
173
|
+
body[:name][:familyName] = name[:family_name] unless name[:family_name].nil?
|
174
|
+
body[:name][:middleName] = name[:middle_name] unless name[:middle_name].nil?
|
175
|
+
body[:userName] = user_name unless user_name.nil?
|
176
|
+
body
|
177
|
+
end
|
178
|
+
|
179
|
+
def compose_operations_param(operations)
|
180
|
+
operations_params = []
|
181
|
+
if operations.is_a?(Array)
|
182
|
+
operations.each do |op|
|
183
|
+
operations_params << {
|
184
|
+
op: op[:op],
|
185
|
+
path: op[:path],
|
186
|
+
valueString: op[:value_string],
|
187
|
+
valueBoolean: op[:value_boolean],
|
188
|
+
valueArray: op[:value_array]
|
189
|
+
}
|
190
|
+
end
|
191
|
+
end
|
192
|
+
operations_params
|
193
|
+
end
|
194
|
+
|
195
|
+
def compose_scim_patch_user_body(user_id, group_id, operations)
|
196
|
+
body = {}
|
197
|
+
body[:userId] = user_id unless user_id.nil?
|
198
|
+
body[:groupId] = group_id unless group_id.nil?
|
199
|
+
body[:operations] = operations unless operations.nil?
|
200
|
+
body
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Descope
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
module Management
|
7
|
+
# Management API calls
|
8
|
+
module SSOSettings
|
9
|
+
include Descope::Api::V1::Management::Common
|
10
|
+
|
11
|
+
def get_sso_settings(tenant_id)
|
12
|
+
# Get SSO settings for the provided tenant id.
|
13
|
+
get(SSO_SETTINGS_PATH, { tenantId: tenant_id })
|
14
|
+
end
|
15
|
+
|
16
|
+
def delete_sso_settings(tenant_id)
|
17
|
+
# Delete SSO settings for the provided tenant id.
|
18
|
+
delete(SSO_SETTINGS_PATH, { tenantId: tenant_id })
|
19
|
+
end
|
20
|
+
|
21
|
+
def create_sso_oidc_app(id: nil, name: nil, description: nil, enabled: nil, logo: nil, login_page_url: nil)
|
22
|
+
body = {}
|
23
|
+
body[:id] = id if id
|
24
|
+
body[:name] = name if name
|
25
|
+
body[:description] = description if description
|
26
|
+
body[:enabled] = enabled if enabled
|
27
|
+
body[:logo] = logo if logo
|
28
|
+
body[:loginPageUrl] = login_page_url if login_page_url
|
29
|
+
post(SSO_OIDC_CREATE_APP_PATH, body)
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_sso_oidc_app(id: nil, name: nil, description: nil, enabled: nil, logo: nil, login_page_url: nil)
|
33
|
+
body = {}
|
34
|
+
body[:id] = id if id
|
35
|
+
body[:name] = name if name
|
36
|
+
body[:description] = description if description
|
37
|
+
body[:enabled] = enabled if enabled
|
38
|
+
body[:logo] = logo if logo
|
39
|
+
body[:loginPageUrl] = login_page_url if login_page_url
|
40
|
+
put(SSO_OIDC_UPDATE_APP_PATH, body)
|
41
|
+
end
|
42
|
+
|
43
|
+
def configure_sso_oidc(tenant_id: nil, settings: nil, redirect_url: nil, domain: nil)
|
44
|
+
raise Descope::ArgumentException.new('SSO settings must be a Hash', code: 400) unless settings.is_a?(Hash)
|
45
|
+
|
46
|
+
# Configure tenant SSO OIDC Settings, using a valid management key.
|
47
|
+
request_params = {
|
48
|
+
tenantId: tenant_id,
|
49
|
+
settings: compose_settings_body(settings),
|
50
|
+
redirectUrl: redirect_url,
|
51
|
+
domain:
|
52
|
+
}
|
53
|
+
post(SSO_OIDC_PATH, request_params)
|
54
|
+
end
|
55
|
+
|
56
|
+
def configure_sso_saml(tenant_id: nil, settings: nil, redirect_url: nil, domain: nil)
|
57
|
+
raise Descope::ArgumentException.new('SSO SAML settings must be a Hash', code: 400) unless settings.is_a?(Hash)
|
58
|
+
|
59
|
+
# Configure tenant SSO SAML Settings, using a valid management key.
|
60
|
+
request_params = {
|
61
|
+
tenantId: tenant_id,
|
62
|
+
settings: compose_settings_body(settings),
|
63
|
+
redirectUrl: redirect_url,
|
64
|
+
domain:
|
65
|
+
}
|
66
|
+
post(SSO_SAML_PATH, request_params)
|
67
|
+
end
|
68
|
+
|
69
|
+
def configure_sso_saml_metadata(tenant_id: nil, settings: nil, redirect_url: nil, domain: nil)
|
70
|
+
# Configure tenant SSO SAML Metadata, using a valid management key.
|
71
|
+
post(SSO_SAML_METADATA_PATH, compose_metadata_body(tenant_id, settings, redirect_url, domain))
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
77
|
+
def compose_settings_body(settings)
|
78
|
+
|
79
|
+
body = {}
|
80
|
+
body[:name] = settings[:name] if settings.key?(:name)
|
81
|
+
body[:clientId] = settings[:client_id] if settings.key?(:client_id)
|
82
|
+
body[:clientSecret] = settings[:client_secret] if settings.key?(:client_secret)
|
83
|
+
body[:redirectUrl] = settings[:redirect_url] if settings.key?(:redirect_url)
|
84
|
+
body[:authUrl] = settings[:auth_url] if settings.key?(:auth_url)
|
85
|
+
body[:tokenUrl] = settings[:token_url] if settings.key?(:token_url)
|
86
|
+
body[:userDataUrl] = settings[:user_data_url] if settings.key?(:user_data_url)
|
87
|
+
body[:scope] = settings[:scope] if settings.key?(:scope)
|
88
|
+
body[:JWKsUrl] = settings[:jwks_url] if settings.key?(:jwks_url)
|
89
|
+
user_mappings = settings[:user_attr_mapping] if settings.key?(:user_attr_mapping)
|
90
|
+
|
91
|
+
# rubocop:disable Metrics/LineLength
|
92
|
+
unless user_mappings.nil? || user_mappings.empty?
|
93
|
+
body[:userAttrMapping] = {}
|
94
|
+
body[:userAttrMapping][:loginId] = user_mappings[:login_id] if settings[:user_attr_mapping].key?(:login_id)
|
95
|
+
body[:userAttrMapping][:username] = user_mappings[:username] if settings[:user_attr_mapping].key?(:username)
|
96
|
+
body[:userAttrMapping][:name] = user_mappings[:name] if settings[:user_attr_mapping].key?(:name)
|
97
|
+
body[:userAttrMapping][:email] = user_mappings[:email] if settings[:user_attr_mapping].key?(:email)
|
98
|
+
body[:userAttrMapping][:phoneNumber] = user_mappings[:phone_number] if settings[:user_attr_mapping].key?(:phone_number)
|
99
|
+
body[:userAttrMapping][:verifiedEmail] = user_mappings[:verified_email] if settings[:user_attr_mapping].key?(:verified_email)
|
100
|
+
body[:userAttrMapping][:verifiedPhone] = user_mappings[:verified_phone] if settings[:user_attr_mapping].key?(:verified_phone)
|
101
|
+
body[:userAttrMapping][:picture] = user_mappings[:picture] if settings[:user_attr_mapping].key?(:picture)
|
102
|
+
body[:userAttrMapping][:givenName] = user_mappings[:given_name] if settings[:user_attr_mapping].key?(:given_name)
|
103
|
+
body[:userAttrMapping][:middleName] = user_mappings[:middle_name] if settings[:user_attr_mapping].key?(:middle_name)
|
104
|
+
body[:userAttrMapping][:familyName] = user_mappings[:family_name] if settings[:user_attr_mapping].key?(:family_name)
|
105
|
+
end
|
106
|
+
|
107
|
+
body[:manageProviderTokens] = settings[:manage_provider_tokens] if settings.key?(:manage_provider_tokens)
|
108
|
+
body[:callbackDomain] = settings[:callback_domain] if settings.key?(:callback_domain)
|
109
|
+
body[:prompt] = settings[:prompt] if settings.key?(:prompt)
|
110
|
+
body[:grantType] = settings[:grant_type] if settings.key?(:grant_type)
|
111
|
+
body[:issuer] = settings[:issuer] if settings.key?(:issuer)
|
112
|
+
|
113
|
+
body
|
114
|
+
end
|
115
|
+
|
116
|
+
def compose_metadata_body(tenant_id, settings, redirect_url, domain)
|
117
|
+
{
|
118
|
+
tenantId: tenant_id,
|
119
|
+
settings: compose_settings_body(settings),
|
120
|
+
redirectUrl: redirect_url,
|
121
|
+
domain:
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
def role_mapping_to_hash(role_mapping)
|
126
|
+
role_mapping ||= []
|
127
|
+
role_mapping_list = []
|
128
|
+
role_mapping.each do |mapping|
|
129
|
+
role_mapping_list << {
|
130
|
+
groups: mapping['groups'],
|
131
|
+
roleName: mapping['role_name']
|
132
|
+
}
|
133
|
+
end
|
134
|
+
role_mapping_list
|
135
|
+
end
|
136
|
+
|
137
|
+
def attribute_mapping_to_hash(attribute_mapping)
|
138
|
+
if attribute_mapping.nil?
|
139
|
+
raise Descope::ArgumentException.new('SSO Attribute mapping cannot be None', code: 400)
|
140
|
+
end
|
141
|
+
|
142
|
+
{
|
143
|
+
name: attribute_mapping['name'],
|
144
|
+
email: attribute_mapping['email'],
|
145
|
+
phoneNumber: attribute_mapping['phone_number'],
|
146
|
+
groups: attribute_mapping['groups']
|
147
|
+
}
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Descope
|
4
|
+
module Api
|
5
|
+
module V1
|
6
|
+
module Management
|
7
|
+
# Management API calls
|
8
|
+
module Tenant
|
9
|
+
include Descope::Mixins::Validation
|
10
|
+
include Descope::Api::V1::Management::Common
|
11
|
+
|
12
|
+
|
13
|
+
def create_tenant(name: nil, id: nil, self_provisioning_domains: nil, custom_attributes: nil)
|
14
|
+
# Create a new tenant with the given name. Tenant IDs are provisioned automatically, but can be provided
|
15
|
+
# explicitly if needed. Both the name and ID must be unique per project.
|
16
|
+
# @see https://docs.descope.com/api/openapi/tenantmanagement/operation/CreateTenant/
|
17
|
+
|
18
|
+
self_provisioning_domains ||= []
|
19
|
+
custom_attributes ||= {}
|
20
|
+
post(TENANT_CREATE_PATH, compose_tenant_create_update_body(name, id, self_provisioning_domains, custom_attributes))
|
21
|
+
end
|
22
|
+
|
23
|
+
def update_tenant(name: nil, id: nil, self_provisioning_domains: nil, custom_attributes: nil)
|
24
|
+
# Update an existing tenant with the given name and domains. IMPORTANT: All parameters are used as overrides
|
25
|
+
# to the existing tenant. Empty fields will override populated fields. Use carefully.
|
26
|
+
# @see https://docs.descope.com/api/openapi/tenantmanagement/operation/UpdateTenant/
|
27
|
+
self_provisioning_domains ||= []
|
28
|
+
custom_attributes ||= {}
|
29
|
+
post(TENANT_UPDATE_PATH, compose_tenant_create_update_body(name, id, self_provisioning_domains, custom_attributes))
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_tenant(id = nil)
|
33
|
+
# Delete an existing tenant. IMPORTANT: This action is irreversible. Use carefully.
|
34
|
+
post(TENANT_DELETE_PATH, { id: })
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_tenant(id = nil)
|
38
|
+
# Load tenant by id.
|
39
|
+
get(TENANT_LOAD_PATH, { id: })
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_all_tenants
|
43
|
+
# Load all tenants.
|
44
|
+
get(TENANT_LOAD_ALL_PATH)
|
45
|
+
end
|
46
|
+
|
47
|
+
def search_all_tenants(ids: nil, names: nil, self_provisioning_domains: nil, custom_attributes: nil)
|
48
|
+
# Search all tenants.
|
49
|
+
request_params = {
|
50
|
+
ids:,
|
51
|
+
names:,
|
52
|
+
selfProvisioningDomains: self_provisioning_domains,
|
53
|
+
customAttributes: custom_attributes
|
54
|
+
}
|
55
|
+
post(TENANT_SEARCH_ALL_PATH, request_params)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def compose_tenant_create_update_body(name, id, self_provisioning_domains, custom_attributes)
|
61
|
+
body = { name:, id: }
|
62
|
+
body[:selfProvisioningDomains] = self_provisioning_domains unless self_provisioning_domains.empty?
|
63
|
+
body[:customAttributes] = custom_attributes unless custom_attributes.empty?
|
64
|
+
|
65
|
+
body
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|