workos 0.11.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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)