workos 0.11.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -0
  3. data/.semaphore/semaphore.yml +2 -2
  4. data/Gemfile.lock +2 -2
  5. data/LICENSE +1 -1
  6. data/lib/workos.rb +2 -0
  7. data/lib/workos/client.rb +3 -2
  8. data/lib/workos/directory.rb +4 -1
  9. data/lib/workos/directory_user.rb +6 -1
  10. data/lib/workos/errors.rb +13 -2
  11. data/lib/workos/organizations.rb +171 -0
  12. data/lib/workos/portal.rb +0 -133
  13. data/lib/workos/profile.rb +8 -10
  14. data/lib/workos/profile_and_token.rb +28 -0
  15. data/lib/workos/sso.rb +31 -100
  16. data/lib/workos/types/directory_struct.rb +1 -0
  17. data/lib/workos/types/directory_user_struct.rb +1 -0
  18. data/lib/workos/version.rb +1 -1
  19. data/spec/lib/workos/organizations_spec.rb +191 -0
  20. data/spec/lib/workos/portal_spec.rb +0 -160
  21. data/spec/lib/workos/sso_spec.rb +41 -122
  22. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_after.yml +12 -9
  23. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_before.yml +8 -5
  24. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_domain.yml +8 -8
  25. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_limit.yml +9 -9
  26. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_no_options.yml +23 -10
  27. data/spec/support/fixtures/vcr_cassettes/directory_sync/list_directories/with_search.yml +8 -8
  28. data/spec/support/fixtures/vcr_cassettes/organization/delete.yml +72 -0
  29. data/spec/support/fixtures/vcr_cassettes/{sso/create_connection_with_invalid_source.yml → organization/delete_invalid.yml} +26 -12
  30. data/spec/support/fixtures/vcr_cassettes/sso/profile.yml +74 -0
  31. data/workos.gemspec +1 -1
  32. metadata +15 -9
  33. data/spec/support/fixtures/vcr_cassettes/sso/create_connection_with_valid_source.yml +0 -63
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64322be12c1dad447bc34d760225e99c47dc6611119ea74dd9a638bac6f23085
4
- data.tar.gz: 99df76eeb89edac09cc58323049efeaad694bf3bd945d07c8d8fb492bb45052f
3
+ metadata.gz: 82fc158535f666670ec2f6f71edd889c24be6a3c9488ffad6c4822f45b9f6ece
4
+ data.tar.gz: d613fb8b9284124c6720c5f95320a205a1e061291a353befa629a0ee1f74151b
5
5
  SHA512:
6
- metadata.gz: 56de86af09e8c79821cb1789b0ceb27db74ac8f11176ff6b43ee36ebe0b18c0bcc60fd459c35dcfa369bd86a70c0f78724861380689c1afcc21296d77d8a9baa
7
- data.tar.gz: b77ac5436b1d5f7a150778c68e259897576689a032d7490835e6ebf7411ba8dc1b3268548648c60261b0273528901a2d63edc3eb4d1e765cf75de7d4448da83e
6
+ metadata.gz: da3e7172612b651a5fd36854deaa480c1bb27032fae2d202bf16eefbfb3914659caa5ce47b1ea8cdac8d8c6cb4995497843ff48f800d870da52ad32f20427323
7
+ data.tar.gz: ab046cdf757eb36e1711c34a56764bfa74265888c605d40a681e75e6184290198cf8249212e6ae316016e72107f7a34f9135330380ac24394c731cc934f0795b
data/.rubocop.yml CHANGED
@@ -20,3 +20,5 @@ Style/TrailingCommaInArguments:
20
20
  EnforcedStyleForMultiline: 'consistent_comma'
21
21
  Style/TrailingCommaInHashLiteral:
22
22
  EnforcedStyleForMultiline: 'consistent_comma'
23
+ AllCops:
24
+ TargetRubyVersion: 2.5
@@ -33,13 +33,13 @@ blocks:
33
33
  - name: Ruby 1.9.3
34
34
  commands:
35
35
  - checkout
36
- - sem-version ruby 1.9.3
36
+ - sem-version ruby 1.9.3-p551
37
37
  - bundle install
38
38
  - bundle exec rspec
39
39
  - name: Ruby 2.0.0
40
40
  commands:
41
41
  - checkout
42
- - sem-version ruby 2.0.0
42
+ - sem-version ruby 2.0.0-p648
43
43
  - bundle install
44
44
  - bundle exec rspec
45
45
  - name: Ruby 2.3.4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- workos (0.11.2)
4
+ workos (1.3.0)
5
5
  sorbet-runtime (~> 0.5)
6
6
 
7
7
  GEM
@@ -60,7 +60,7 @@ GEM
60
60
  simplecov_json_formatter (0.1.2)
61
61
  sorbet (0.5.6388)
62
62
  sorbet-static (= 0.5.6388)
63
- sorbet-runtime (0.5.6403)
63
+ sorbet-runtime (0.5.6433)
64
64
  sorbet-static (0.5.6388-universal-darwin-14)
65
65
  sorbet-static (0.5.6388-universal-darwin-15)
66
66
  sorbet-static (0.5.6388-universal-darwin-16)
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2019 WorkOS
3
+ Copyright (c) 2021 WorkOS
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/lib/workos.rb CHANGED
@@ -35,9 +35,11 @@ module WorkOS
35
35
  autoload :Directory, 'workos/directory'
36
36
  autoload :DirectoryGroup, 'workos/directory_group'
37
37
  autoload :Organization, 'workos/organization'
38
+ autoload :Organizations, 'workos/organizations'
38
39
  autoload :Passwordless, 'workos/passwordless'
39
40
  autoload :Portal, 'workos/portal'
40
41
  autoload :Profile, 'workos/profile'
42
+ autoload :ProfileAndToken, 'workos/profile_and_token'
41
43
  autoload :SSO, 'workos/sso'
42
44
  autoload :DirectoryUser, 'workos/directory_user'
43
45
 
data/lib/workos/client.rb CHANGED
@@ -36,9 +36,10 @@ module WorkOS
36
36
  path: String,
37
37
  auth: T.nilable(T::Boolean),
38
38
  params: T.nilable(Hash),
39
+ access_token: T.nilable(String),
39
40
  ).returns(Net::HTTP::Get)
40
41
  end
41
- def get_request(path:, auth: false, params: {})
42
+ def get_request(path:, auth: false, params: {}, access_token: nil)
42
43
  uri = URI(path)
43
44
  uri.query = URI.encode_www_form(params) if params
44
45
 
@@ -47,7 +48,7 @@ module WorkOS
47
48
  'Content-Type' => 'application/json',
48
49
  )
49
50
 
50
- request['Authorization'] = "Bearer #{WorkOS.key!}" if auth
51
+ request['Authorization'] = "Bearer #{access_token || WorkOS.key!}" if auth
51
52
  request['User-Agent'] = user_agent
52
53
  request
53
54
  end
@@ -8,7 +8,7 @@ module WorkOS
8
8
  class Directory
9
9
  extend T::Sig
10
10
 
11
- attr_accessor :id, :domain, :name, :type, :state
11
+ attr_accessor :id, :domain, :name, :type, :state, :organization_id
12
12
 
13
13
  sig { params(json: String).void }
14
14
  def initialize(json)
@@ -19,6 +19,7 @@ module WorkOS
19
19
  @domain = T.let(raw.domain, String)
20
20
  @type = T.let(raw.type, String)
21
21
  @state = T.let(raw.state, String)
22
+ @organization_id = T.let(raw.organization_id, String)
22
23
  end
23
24
 
24
25
  def to_json(*)
@@ -28,6 +29,7 @@ module WorkOS
28
29
  domain: domain,
29
30
  type: type,
30
31
  state: state,
32
+ organization_id: organization_id,
31
33
  }
32
34
  end
33
35
 
@@ -47,6 +49,7 @@ module WorkOS
47
49
  domain: hash[:domain],
48
50
  type: hash[:type],
49
51
  state: hash[:state],
52
+ organization_id: hash[:organization_id],
50
53
  )
51
54
  end
52
55
  end
@@ -9,8 +9,9 @@ module WorkOS
9
9
  extend T::Sig
10
10
 
11
11
  attr_accessor :id, :idp_id, :emails, :first_name, :last_name, :username, :state,
12
- :raw_attributes
12
+ :groups, :raw_attributes
13
13
 
14
+ # rubocop:disable Metrics/AbcSize
14
15
  sig { params(json: String).void }
15
16
  def initialize(json)
16
17
  raw = parse_json(json)
@@ -22,8 +23,10 @@ module WorkOS
22
23
  @last_name = raw.last_name
23
24
  @username = raw.username
24
25
  @state = raw.state
26
+ @groups = T.let(raw.groups, Array)
25
27
  @raw_attributes = raw.raw_attributes
26
28
  end
29
+ # rubocop:enable Metrics/AbcSize
27
30
 
28
31
  def to_json(*)
29
32
  {
@@ -34,6 +37,7 @@ module WorkOS
34
37
  last_name: last_name,
35
38
  username: username,
36
39
  state: state,
40
+ groups: groups,
37
41
  raw_attributes: raw_attributes,
38
42
  }
39
43
  end
@@ -56,6 +60,7 @@ module WorkOS
56
60
  last_name: hash[:last_name],
57
61
  username: hash[:username],
58
62
  state: hash[:state],
63
+ groups: hash[:groups],
59
64
  raw_attributes: hash[:raw_attributes],
60
65
  )
61
66
  end
data/lib/workos/errors.rb CHANGED
@@ -13,12 +13,16 @@ module WorkOS
13
13
  sig do
14
14
  params(
15
15
  message: T.nilable(String),
16
+ error: T.nilable(String),
17
+ error_description: T.nilable(String),
16
18
  http_status: T.nilable(Integer),
17
19
  request_id: T.nilable(String),
18
20
  ).void
19
21
  end
20
- def initialize(message: nil, http_status: nil, request_id: nil)
22
+ def initialize(message: nil, error: nil, error_description: nil, http_status: nil, request_id: nil)
21
23
  @message = message
24
+ @error = error
25
+ @error_description = error_description
22
26
  @http_status = http_status
23
27
  @request_id = request_id
24
28
  end
@@ -27,7 +31,14 @@ module WorkOS
27
31
  def to_s
28
32
  status_string = @http_status.nil? ? '' : "Status #{@http_status}, "
29
33
  id_string = @request_id.nil? ? '' : " - request ID: #{@request_id}"
30
- "#{status_string}#{@message}#{id_string}"
34
+ if @error && @error_description
35
+ error_string = "error: #{@error}, error_description: #{@error_description}"
36
+ "#{status_string}#{error_string}#{id_string}"
37
+ elsif @error
38
+ "#{status_string}#{@error}#{id_string}"
39
+ else
40
+ "#{status_string}#{@message}#{id_string}"
41
+ end
31
42
  end
32
43
  end
33
44
 
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+ # typed: true
3
+
4
+ require 'net/http'
5
+
6
+ module WorkOS
7
+ # The Organizations module provides resource methods for working with Organizations
8
+ module Organizations
9
+ class << self
10
+ extend T::Sig
11
+ include Base
12
+ include Client
13
+
14
+ # Retrieve a list of organizations that have connections configured
15
+ # within your WorkOS dashboard.
16
+ #
17
+ # @param [Array<String>] domains Filter organizations to only return those
18
+ # that are associated with the provided domains.
19
+ # @param [String] before A pagination argument used to request
20
+ # organizations before the provided Organization ID.
21
+ # @param [String] after A pagination argument used to request
22
+ # organizations after the provided Organization ID.
23
+ # @param [Integer] limit A pagination argument used to limit the number
24
+ # of listed Organizations that are returned.
25
+ sig do
26
+ params(
27
+ options: T::Hash[Symbol, String],
28
+ ).returns(WorkOS::Types::ListStruct)
29
+ end
30
+ def list_organizations(options = {})
31
+ response = execute_request(
32
+ request: get_request(
33
+ path: '/organizations',
34
+ auth: true,
35
+ params: options,
36
+ ),
37
+ )
38
+
39
+ parsed_response = JSON.parse(response.body)
40
+
41
+ organizations = parsed_response['data'].map do |organization|
42
+ ::WorkOS::Organization.new(organization.to_json)
43
+ end
44
+
45
+ WorkOS::Types::ListStruct.new(
46
+ data: organizations,
47
+ list_metadata: parsed_response['listMetadata'],
48
+ )
49
+ end
50
+
51
+ # Get an Organization
52
+ #
53
+ # @param [String] id Organization unique identifier
54
+ #
55
+ # @example
56
+ # WorkOS::Portal.get_organization(id: 'org_02DRA1XNSJDZ19A31F183ECQW9')
57
+ # => #<WorkOS::Organization:0x00007fb6e4193d20
58
+ # @id="org_02DRA1XNSJDZ19A31F183ECQW9",
59
+ # @name="Foo Corp",
60
+ # @domains=
61
+ # [{:object=>"organization_domain",
62
+ # :id=>"org_domain_01E6PK9N3XMD8RHWF7S66380AR",
63
+ # :domain=>"foo-corp.com"}]>
64
+ #
65
+ # @return [WorkOS::Organization]
66
+ sig { params(id: String).returns(WorkOS::Organization) }
67
+ def get_organization(id:)
68
+ request = get_request(
69
+ auth: true,
70
+ path: "/organizations/#{id}",
71
+ )
72
+
73
+ response = execute_request(request: request)
74
+
75
+ WorkOS::Organization.new(response.body)
76
+ end
77
+
78
+ # Create an organization
79
+ #
80
+ # @param [Array<String>] domains List of domains that belong to the
81
+ # organization
82
+ # @param [String] name A unique, descriptive name for the organization
83
+ sig do
84
+ params(
85
+ domains: T::Array[String],
86
+ name: String,
87
+ ).returns(WorkOS::Organization)
88
+ end
89
+ def create_organization(domains:, name:)
90
+ request = post_request(
91
+ auth: true,
92
+ body: { domains: domains, name: name },
93
+ path: '/organizations',
94
+ )
95
+
96
+ response = execute_request(request: request)
97
+ check_and_raise_organization_error(response: response)
98
+
99
+ WorkOS::Organization.new(response.body)
100
+ end
101
+
102
+ # Update an organization
103
+ #
104
+ # @param [String] organization Organization unique identifier
105
+ # @param [Array<String>] domains List of domains that belong to the
106
+ # organization
107
+ # @param [String] name A unique, descriptive name for the organization
108
+ sig do
109
+ params(
110
+ organization: String,
111
+ domains: T::Array[String],
112
+ name: String,
113
+ ).returns(WorkOS::Organization)
114
+ end
115
+ def update_organization(organization:, domains:, name:)
116
+ request = put_request(
117
+ auth: true,
118
+ body: { domains: domains, name: name },
119
+ path: "/organizations/#{organization}",
120
+ )
121
+
122
+ response = execute_request(request: request)
123
+ check_and_raise_organization_error(response: response)
124
+
125
+ WorkOS::Organization.new(response.body)
126
+ end
127
+
128
+ # Delete an Organization
129
+ #
130
+ # @param [String] id Organization unique identifier
131
+ #
132
+ # @example
133
+ # WorkOS::SSO.delete_organization(id: 'org_01EHZNVPK3SFK441A1RGBFSHRT')
134
+ # => true
135
+ #
136
+ # @return [Bool] - returns `true` if successful
137
+ sig { params(id: String).returns(T::Boolean) }
138
+ def delete_organization(id:)
139
+ request = delete_request(
140
+ auth: true,
141
+ path: "/organizations/#{id}",
142
+ )
143
+
144
+ response = execute_request(request: request)
145
+
146
+ response.is_a? Net::HTTPSuccess
147
+ end
148
+
149
+ private
150
+
151
+ sig { params(response: Net::HTTPResponse).void }
152
+ def check_and_raise_organization_error(response:)
153
+ begin
154
+ body = JSON.parse(response.body)
155
+ return unless body['message']
156
+
157
+ message = body['message']
158
+ request_id = response['x-request-id']
159
+ rescue StandardError
160
+ message = 'Something went wrong'
161
+ end
162
+
163
+ raise APIError.new(
164
+ message: message,
165
+ http_status: nil,
166
+ request_id: request_id,
167
+ )
168
+ end
169
+ end
170
+ end
171
+ end
data/lib/workos/portal.rb CHANGED
@@ -15,30 +15,6 @@ module WorkOS
15
15
  GENERATE_LINK_INTENTS = WorkOS::Types::Intent.values.map(&:serialize).
16
16
  freeze
17
17
 
18
- # Create an organization
19
- #
20
- # @param [Array<String>] domains List of domains that belong to the
21
- # organization
22
- # @param [String] name A unique, descriptive name for the organization
23
- sig do
24
- params(
25
- domains: T::Array[String],
26
- name: String,
27
- ).returns(WorkOS::Organization)
28
- end
29
- def create_organization(domains:, name:)
30
- request = post_request(
31
- auth: true,
32
- body: { domains: domains, name: name },
33
- path: '/organizations',
34
- )
35
-
36
- response = execute_request(request: request)
37
- check_and_raise_organization_error(response: response)
38
-
39
- WorkOS::Organization.new(response.body)
40
- end
41
-
42
18
  # Generate a link to grant access to an organization's Admin Portal
43
19
  #
44
20
  # @param [String] intent The access scope for the generated Admin Portal
@@ -73,117 +49,8 @@ module WorkOS
73
49
  JSON.parse(response.body)['link']
74
50
  end
75
51
 
76
- # Retrieve a list of organizations that have connections configured
77
- # within your WorkOS dashboard.
78
- #
79
- # @param [Array<String>] domains Filter organizations to only return those
80
- # that are associated with the provided domains.
81
- # @param [String] before A pagination argument used to request
82
- # organizations before the provided Organization ID.
83
- # @param [String] after A pagination argument used to request
84
- # organizations after the provided Organization ID.
85
- # @param [Integer] limit A pagination argument used to limit the number
86
- # of listed Organizations that are returned.
87
- sig do
88
- params(
89
- options: T::Hash[Symbol, String],
90
- ).returns(WorkOS::Types::ListStruct)
91
- end
92
- def list_organizations(options = {})
93
- response = execute_request(
94
- request: get_request(
95
- path: '/organizations',
96
- auth: true,
97
- params: options,
98
- ),
99
- )
100
-
101
- parsed_response = JSON.parse(response.body)
102
-
103
- organizations = parsed_response['data'].map do |organization|
104
- ::WorkOS::Organization.new(organization.to_json)
105
- end
106
-
107
- WorkOS::Types::ListStruct.new(
108
- data: organizations,
109
- list_metadata: parsed_response['listMetadata'],
110
- )
111
- end
112
-
113
- # Get an Organization
114
- #
115
- # @param [String] id Organization unique identifier
116
- #
117
- # @example
118
- # WorkOS::Portal.get_organization(id: 'org_02DRA1XNSJDZ19A31F183ECQW9')
119
- # => #<WorkOS::Organization:0x00007fb6e4193d20
120
- # @id="org_02DRA1XNSJDZ19A31F183ECQW9",
121
- # @name="Foo Corp",
122
- # @domains=
123
- # [{:object=>"organization_domain",
124
- # :id=>"org_domain_01E6PK9N3XMD8RHWF7S66380AR",
125
- # :domain=>"foo-corp.com"}]>
126
- #
127
- # @return [WorkOS::Connection]
128
- sig { params(id: String).returns(WorkOS::Organization) }
129
- def get_organization(id:)
130
- request = get_request(
131
- auth: true,
132
- path: "/organizations/#{id}",
133
- )
134
-
135
- response = execute_request(request: request)
136
-
137
- WorkOS::Organization.new(response.body)
138
- end
139
-
140
- # Update an organization
141
- #
142
- # @param [String] organization Organization unique identifier
143
- # @param [Array<String>] domains List of domains that belong to the
144
- # organization
145
- # @param [String] name A unique, descriptive name for the organization
146
- sig do
147
- params(
148
- organization: String,
149
- domains: T::Array[String],
150
- name: String,
151
- ).returns(WorkOS::Organization)
152
- end
153
- def update_organization(organization:, domains:, name:)
154
- request = put_request(
155
- auth: true,
156
- body: { domains: domains, name: name },
157
- path: "/organizations/#{organization}",
158
- )
159
-
160
- response = execute_request(request: request)
161
- check_and_raise_organization_error(response: response)
162
-
163
- WorkOS::Organization.new(response.body)
164
- end
165
-
166
52
  private
167
53
 
168
- sig { params(response: Net::HTTPResponse).void }
169
- def check_and_raise_organization_error(response:)
170
- begin
171
- body = JSON.parse(response.body)
172
- return unless body['message']
173
-
174
- message = body['message']
175
- request_id = response['x-request-id']
176
- rescue StandardError
177
- message = 'Something went wrong'
178
- end
179
-
180
- raise APIError.new(
181
- message: message,
182
- http_status: nil,
183
- request_id: request_id,
184
- )
185
- end
186
-
187
54
  sig { params(intent: String).void }
188
55
  def validate_intent(intent)
189
56
  return if GENERATE_LINK_INTENTS.include?(intent)