descope 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (197) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yaml +54 -0
  3. data/.gitignore +59 -0
  4. data/.release-please-manifest.json +3 -0
  5. data/.rubocop.yml +10 -0
  6. data/.rubocop_todo.yml +10 -0
  7. data/.ruby-version +1 -0
  8. data/CHANGELOG.md +90 -0
  9. data/Gemfile +22 -0
  10. data/Gemfile.lock +204 -0
  11. data/LICENSE +21 -0
  12. data/README.md +1171 -0
  13. data/Rakefile +31 -0
  14. data/descope.gemspec +34 -0
  15. data/examples/ruby/Gemfile +4 -0
  16. data/examples/ruby/Gemfile.lock +41 -0
  17. data/examples/ruby/access_key_app.rb +45 -0
  18. data/examples/ruby/enchantedlink_app.rb +65 -0
  19. data/examples/ruby/magiclink_app.rb +81 -0
  20. data/examples/ruby/management/Gemfile +5 -0
  21. data/examples/ruby/management/Gemfile.lock +38 -0
  22. data/examples/ruby/management/access_key_app.rb +71 -0
  23. data/examples/ruby/management/audit_app.rb +25 -0
  24. data/examples/ruby/management/authz_app.rb +135 -0
  25. data/examples/ruby/management/authz_files.json +229 -0
  26. data/examples/ruby/management/flow_app.rb +57 -0
  27. data/examples/ruby/management/permission_app.rb +56 -0
  28. data/examples/ruby/management/role_app.rb +58 -0
  29. data/examples/ruby/management/tenant_app.rb +60 -0
  30. data/examples/ruby/management/user_app.rb +60 -0
  31. data/examples/ruby/oauth_app.rb +39 -0
  32. data/examples/ruby/otp_app.rb +50 -0
  33. data/examples/ruby/password_app.rb +76 -0
  34. data/examples/ruby/saml_app.rb +38 -0
  35. data/examples/ruby-on-rails-api/descope/.dockerignore +37 -0
  36. data/examples/ruby-on-rails-api/descope/.gitattributes +9 -0
  37. data/examples/ruby-on-rails-api/descope/.gitignore +40 -0
  38. data/examples/ruby-on-rails-api/descope/.node-version +1 -0
  39. data/examples/ruby-on-rails-api/descope/.ruby-version +1 -0
  40. data/examples/ruby-on-rails-api/descope/Dockerfile +75 -0
  41. data/examples/ruby-on-rails-api/descope/Gemfile +67 -0
  42. data/examples/ruby-on-rails-api/descope/Gemfile.lock +284 -0
  43. data/examples/ruby-on-rails-api/descope/Procfile.dev +3 -0
  44. data/examples/ruby-on-rails-api/descope/README.md +54 -0
  45. data/examples/ruby-on-rails-api/descope/Rakefile +6 -0
  46. data/examples/ruby-on-rails-api/descope/app/assets/builds/.keep +0 -0
  47. data/examples/ruby-on-rails-api/descope/app/assets/config/manifest.js +3 -0
  48. data/examples/ruby-on-rails-api/descope/app/assets/images/.keep +0 -0
  49. data/examples/ruby-on-rails-api/descope/app/assets/images/descope.jpeg +0 -0
  50. data/examples/ruby-on-rails-api/descope/app/assets/images/favicon.ico +0 -0
  51. data/examples/ruby-on-rails-api/descope/app/assets/images/logo192.png +0 -0
  52. data/examples/ruby-on-rails-api/descope/app/assets/images/logo512.png +0 -0
  53. data/examples/ruby-on-rails-api/descope/app/assets/stylesheets/application.bootstrap.scss +67 -0
  54. data/examples/ruby-on-rails-api/descope/app/channels/application_cable/channel.rb +4 -0
  55. data/examples/ruby-on-rails-api/descope/app/channels/application_cable/connection.rb +4 -0
  56. data/examples/ruby-on-rails-api/descope/app/controllers/application_controller.rb +2 -0
  57. data/examples/ruby-on-rails-api/descope/app/controllers/concerns/.keep +0 -0
  58. data/examples/ruby-on-rails-api/descope/app/controllers/homepage_controller.rb +4 -0
  59. data/examples/ruby-on-rails-api/descope/app/controllers/session_controller.rb +66 -0
  60. data/examples/ruby-on-rails-api/descope/app/helpers/application_helper.rb +2 -0
  61. data/examples/ruby-on-rails-api/descope/app/helpers/homepage_helper.rb +2 -0
  62. data/examples/ruby-on-rails-api/descope/app/helpers/session_helper.rb +2 -0
  63. data/examples/ruby-on-rails-api/descope/app/javascript/App.css +53 -0
  64. data/examples/ruby-on-rails-api/descope/app/javascript/application.js +5 -0
  65. data/examples/ruby-on-rails-api/descope/app/javascript/components/App.jsx +4 -0
  66. data/examples/ruby-on-rails-api/descope/app/javascript/components/Dashboard.jsx +60 -0
  67. data/examples/ruby-on-rails-api/descope/app/javascript/components/Home.jsx +27 -0
  68. data/examples/ruby-on-rails-api/descope/app/javascript/components/Login.jsx +45 -0
  69. data/examples/ruby-on-rails-api/descope/app/javascript/components/Profile.jsx +81 -0
  70. data/examples/ruby-on-rails-api/descope/app/javascript/components/index.html +11 -0
  71. data/examples/ruby-on-rails-api/descope/app/javascript/components/index.jsx +24 -0
  72. data/examples/ruby-on-rails-api/descope/app/javascript/controllers/application.js +9 -0
  73. data/examples/ruby-on-rails-api/descope/app/javascript/controllers/index.js +5 -0
  74. data/examples/ruby-on-rails-api/descope/app/javascript/reportWebVitals.js +13 -0
  75. data/examples/ruby-on-rails-api/descope/app/javascript/routes/index.jsx +17 -0
  76. data/examples/ruby-on-rails-api/descope/app/jobs/application_job.rb +7 -0
  77. data/examples/ruby-on-rails-api/descope/app/mailers/application_mailer.rb +4 -0
  78. data/examples/ruby-on-rails-api/descope/app/models/application_record.rb +3 -0
  79. data/examples/ruby-on-rails-api/descope/app/models/concerns/.keep +0 -0
  80. data/examples/ruby-on-rails-api/descope/app/views/homepage/index.html.erb +2 -0
  81. data/examples/ruby-on-rails-api/descope/app/views/layouts/application.html.erb +16 -0
  82. data/examples/ruby-on-rails-api/descope/app/views/layouts/mailer.html.erb +13 -0
  83. data/examples/ruby-on-rails-api/descope/app/views/layouts/mailer.text.erb +1 -0
  84. data/examples/ruby-on-rails-api/descope/app/views/session/index.html.erb +2 -0
  85. data/examples/ruby-on-rails-api/descope/bin/bundle +109 -0
  86. data/examples/ruby-on-rails-api/descope/bin/dev +11 -0
  87. data/examples/ruby-on-rails-api/descope/bin/docker-entrypoint +8 -0
  88. data/examples/ruby-on-rails-api/descope/bin/rails +4 -0
  89. data/examples/ruby-on-rails-api/descope/bin/rake +4 -0
  90. data/examples/ruby-on-rails-api/descope/bin/setup +36 -0
  91. data/examples/ruby-on-rails-api/descope/build.js +30 -0
  92. data/examples/ruby-on-rails-api/descope/config/application.rb +42 -0
  93. data/examples/ruby-on-rails-api/descope/config/boot.rb +4 -0
  94. data/examples/ruby-on-rails-api/descope/config/cable.yml +10 -0
  95. data/examples/ruby-on-rails-api/descope/config/config.yml +9 -0
  96. data/examples/ruby-on-rails-api/descope/config/credentials.yml.enc +1 -0
  97. data/examples/ruby-on-rails-api/descope/config/database.yml +25 -0
  98. data/examples/ruby-on-rails-api/descope/config/environment.rb +5 -0
  99. data/examples/ruby-on-rails-api/descope/config/environments/development.rb +76 -0
  100. data/examples/ruby-on-rails-api/descope/config/environments/production.rb +97 -0
  101. data/examples/ruby-on-rails-api/descope/config/environments/test.rb +64 -0
  102. data/examples/ruby-on-rails-api/descope/config/initializers/assets.rb +13 -0
  103. data/examples/ruby-on-rails-api/descope/config/initializers/content_security_policy.rb +25 -0
  104. data/examples/ruby-on-rails-api/descope/config/initializers/filter_parameter_logging.rb +8 -0
  105. data/examples/ruby-on-rails-api/descope/config/initializers/inflections.rb +16 -0
  106. data/examples/ruby-on-rails-api/descope/config/initializers/load_config.rb +12 -0
  107. data/examples/ruby-on-rails-api/descope/config/initializers/permissions_policy.rb +13 -0
  108. data/examples/ruby-on-rails-api/descope/config/locales/en.yml +31 -0
  109. data/examples/ruby-on-rails-api/descope/config/puma.rb +35 -0
  110. data/examples/ruby-on-rails-api/descope/config/routes.rb +18 -0
  111. data/examples/ruby-on-rails-api/descope/config/storage.yml +34 -0
  112. data/examples/ruby-on-rails-api/descope/config.ru +6 -0
  113. data/examples/ruby-on-rails-api/descope/db/seeds.rb +9 -0
  114. data/examples/ruby-on-rails-api/descope/lib/assets/.keep +0 -0
  115. data/examples/ruby-on-rails-api/descope/lib/tasks/.keep +0 -0
  116. data/examples/ruby-on-rails-api/descope/log/.keep +0 -0
  117. data/examples/ruby-on-rails-api/descope/package-lock.json +19680 -0
  118. data/examples/ruby-on-rails-api/descope/package.json +51 -0
  119. data/examples/ruby-on-rails-api/descope/public/404.html +67 -0
  120. data/examples/ruby-on-rails-api/descope/public/422.html +67 -0
  121. data/examples/ruby-on-rails-api/descope/public/500.html +66 -0
  122. data/examples/ruby-on-rails-api/descope/public/apple-touch-icon-precomposed.png +0 -0
  123. data/examples/ruby-on-rails-api/descope/public/apple-touch-icon.png +0 -0
  124. data/examples/ruby-on-rails-api/descope/public/favicon.ico +0 -0
  125. data/examples/ruby-on-rails-api/descope/public/robots.txt +1 -0
  126. data/examples/ruby-on-rails-api/descope/storage/.keep +0 -0
  127. data/examples/ruby-on-rails-api/descope/tmp/.keep +0 -0
  128. data/examples/ruby-on-rails-api/descope/tmp/pids/.keep +0 -0
  129. data/examples/ruby-on-rails-api/descope/tmp/storage/.keep +0 -0
  130. data/examples/ruby-on-rails-api/descope/vendor/.keep +0 -0
  131. data/examples/ruby-on-rails-api/descope/yarn.lock +10780 -0
  132. data/lib/descope/api/v1/auth/enchantedlink.rb +156 -0
  133. data/lib/descope/api/v1/auth/magiclink.rb +170 -0
  134. data/lib/descope/api/v1/auth/oauth.rb +72 -0
  135. data/lib/descope/api/v1/auth/otp.rb +186 -0
  136. data/lib/descope/api/v1/auth/password.rb +100 -0
  137. data/lib/descope/api/v1/auth/saml.rb +48 -0
  138. data/lib/descope/api/v1/auth/totp.rb +72 -0
  139. data/lib/descope/api/v1/auth.rb +452 -0
  140. data/lib/descope/api/v1/management/access_key.rb +81 -0
  141. data/lib/descope/api/v1/management/audit.rb +82 -0
  142. data/lib/descope/api/v1/management/authz.rb +165 -0
  143. data/lib/descope/api/v1/management/common.rb +147 -0
  144. data/lib/descope/api/v1/management/flow.rb +55 -0
  145. data/lib/descope/api/v1/management/password.rb +58 -0
  146. data/lib/descope/api/v1/management/permission.rb +48 -0
  147. data/lib/descope/api/v1/management/project.rb +53 -0
  148. data/lib/descope/api/v1/management/role.rb +48 -0
  149. data/lib/descope/api/v1/management/scim.rb +206 -0
  150. data/lib/descope/api/v1/management/sso_settings.rb +153 -0
  151. data/lib/descope/api/v1/management/tenant.rb +71 -0
  152. data/lib/descope/api/v1/management/user.rb +619 -0
  153. data/lib/descope/api/v1/management.rb +38 -0
  154. data/lib/descope/api/v1/session.rb +84 -0
  155. data/lib/descope/api/v1.rb +13 -0
  156. data/lib/descope/client.rb +6 -0
  157. data/lib/descope/exception.rb +50 -0
  158. data/lib/descope/mixins/common.rb +129 -0
  159. data/lib/descope/mixins/headers.rb +15 -0
  160. data/lib/descope/mixins/http.rb +133 -0
  161. data/lib/descope/mixins/initializer.rb +80 -0
  162. data/lib/descope/mixins/logging.rb +30 -0
  163. data/lib/descope/mixins/validation.rb +79 -0
  164. data/lib/descope/mixins.rb +22 -0
  165. data/lib/descope/version.rb +7 -0
  166. data/lib/descope.rb +9 -0
  167. data/lib/descope_client.rb +5 -0
  168. data/release-please-config.json +18 -0
  169. data/renovate.json +6 -0
  170. data/spec/factories/user.rb +16 -0
  171. data/spec/lib.descope/api/v1/auth/enchantedlink_spec.rb +159 -0
  172. data/spec/lib.descope/api/v1/auth/magiclink_spec.rb +282 -0
  173. data/spec/lib.descope/api/v1/auth/oauth_spec.rb +117 -0
  174. data/spec/lib.descope/api/v1/auth/otp_spec.rb +285 -0
  175. data/spec/lib.descope/api/v1/auth/password_spec.rb +124 -0
  176. data/spec/lib.descope/api/v1/auth/saml_spec.rb +55 -0
  177. data/spec/lib.descope/api/v1/auth/totp_spec.rb +70 -0
  178. data/spec/lib.descope/api/v1/auth_spec.rb +372 -0
  179. data/spec/lib.descope/api/v1/management/access_key_spec.rb +118 -0
  180. data/spec/lib.descope/api/v1/management/audit_spec.rb +78 -0
  181. data/spec/lib.descope/api/v1/management/authz_spec.rb +336 -0
  182. data/spec/lib.descope/api/v1/management/flow_spec.rb +78 -0
  183. data/spec/lib.descope/api/v1/management/password_spec.rb +25 -0
  184. data/spec/lib.descope/api/v1/management/permission_spec.rb +81 -0
  185. data/spec/lib.descope/api/v1/management/project_spec.rb +63 -0
  186. data/spec/lib.descope/api/v1/management/role_spec.rb +85 -0
  187. data/spec/lib.descope/api/v1/management/scim_spec.rb +312 -0
  188. data/spec/lib.descope/api/v1/management/sso_settings_spec.rb +172 -0
  189. data/spec/lib.descope/api/v1/management/tenant_spec.rb +141 -0
  190. data/spec/lib.descope/api/v1/management/user_spec.rb +667 -0
  191. data/spec/lib.descope/api/v1/session_spec.rb +117 -0
  192. data/spec/lib.descope/client_spec.rb +40 -0
  193. data/spec/spec_helper.rb +72 -0
  194. data/spec/support/client_config.rb +14 -0
  195. data/spec/support/dummy_class.rb +36 -0
  196. data/spec/support/utils.rb +32 -0
  197. 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