workos 7.1.2 → 8.0.1
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.
- checksums.yaml +4 -4
- data/.github/workflows/docs.yml +49 -0
- data/.github/workflows/release-please.yml +2 -2
- data/.gitignore +2 -0
- data/.last-synced-sha +1 -1
- data/.oagen-manifest.json +61 -40
- data/.release-please-manifest.json +1 -1
- data/.yardopts +6 -0
- data/CHANGELOG.md +36 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +33 -2
- data/README.md +19 -0
- data/docs/V7_MIGRATION_GUIDE.md +21 -0
- data/lib/workos/actions.rb +1 -1
- data/lib/workos/api_keys/api_key.rb +1 -1
- data/lib/workos/api_keys/api_key_created_data.rb +1 -1
- data/lib/workos/api_keys/organization_api_key.rb +43 -0
- data/lib/workos/{types/events_order.rb → api_keys/organization_api_key_owner.rb} +1 -3
- data/lib/workos/api_keys/organization_api_key_with_value.rb +46 -0
- data/lib/workos/{types/audit_logs_order.rb → api_keys/organization_api_key_with_value_owner.rb} +1 -3
- data/lib/workos/api_keys.rb +46 -46
- data/lib/workos/audit_logs.rb +4 -4
- data/lib/workos/authorization/user_organization_membership_base_list_data.rb +5 -2
- data/lib/workos/authorization/{role_assignment.rb → user_role_assignment.rb} +5 -2
- data/lib/workos/authorization/{role_assignment_resource.rb → user_role_assignment_resource.rb} +1 -1
- data/lib/workos/authorization.rb +122 -22
- data/lib/workos/base_client.rb +71 -5
- data/lib/workos/client.rb +4 -4
- data/lib/workos/connect.rb +2 -2
- data/lib/workos/directory_sync/directory_user.rb +3 -0
- data/lib/workos/directory_sync/directory_user_with_groups.rb +4 -1
- data/lib/workos/directory_sync/dsync_user_updated_data.rb +3 -0
- data/lib/workos/directory_sync.rb +6 -6
- data/lib/workos/encryptors/aes_gcm.rb +19 -5
- data/lib/workos/events.rb +2 -2
- data/lib/workos/feature_flags.rb +6 -6
- data/lib/workos/groups.rb +4 -4
- data/lib/workos/multi_factor_auth.rb +2 -2
- data/lib/workos/organizations.rb +2 -2
- data/lib/workos/session.rb +28 -7
- data/lib/workos/session_manager.rb +24 -1
- data/lib/workos/sso/profile.rb +3 -0
- data/lib/workos/sso.rb +2 -2
- data/lib/workos/types/event_context_actor_source.rb +2 -1
- data/lib/workos/types/{applications_order.rb → pagination_order.rb} +1 -1
- data/lib/workos/types/{vault_byok_key_verification_completed_data_key_provider.rb → vault_byok_key_provider.rb} +1 -1
- data/lib/workos/user_management/create_user_api_key.rb +25 -0
- data/lib/workos/user_management/organization_membership.rb +5 -2
- data/lib/workos/user_management/user_api_key.rb +43 -0
- data/lib/workos/user_management/user_api_key_created_data_owner.rb +25 -0
- data/lib/workos/{api_keys/api_key_with_value_owner.rb → user_management/user_api_key_owner.rb} +1 -1
- data/lib/workos/{types/webhooks_order.rb → user_management/user_api_key_revoked_data_owner.rb} +1 -3
- data/lib/workos/{api_keys/api_key_with_value.rb → user_management/user_api_key_with_value.rb} +2 -2
- data/lib/workos/{types/groups_order.rb → user_management/user_api_key_with_value_owner.rb} +1 -3
- data/lib/workos/user_management/user_organization_membership.rb +5 -2
- data/lib/workos/user_management.rb +114 -10
- data/lib/workos/user_management_organization_membership_groups.rb +2 -2
- data/lib/workos/vault/vault_byok_key_deleted.rb +34 -0
- data/lib/workos/vault/vault_byok_key_deleted_data.rb +22 -0
- data/lib/workos/version.rb +1 -1
- data/lib/workos/webhooks.rb +3 -3
- data/rbi/workos/api_key.rbi +2 -2
- data/rbi/workos/api_key_created_data.rbi +2 -2
- data/rbi/workos/api_key_revoked_data.rbi +2 -2
- data/rbi/workos/api_keys.rbi +17 -17
- data/rbi/workos/authorization.rbi +27 -1
- data/rbi/workos/client.rbi +3 -3
- data/rbi/workos/create_user_api_key.rbi +36 -0
- data/rbi/workos/directory_user.rbi +6 -0
- data/rbi/workos/directory_user_with_groups.rbi +6 -0
- data/rbi/workos/dsync_user_updated_data.rbi +6 -0
- data/rbi/workos/organization_api_key.rbi +72 -0
- data/rbi/workos/{api_key_with_value_owner.rbi → organization_api_key_owner.rbi} +1 -1
- data/rbi/workos/organization_api_key_with_value.rbi +78 -0
- data/rbi/workos/organization_api_key_with_value_owner.rbi +30 -0
- data/rbi/workos/organization_membership.rbi +6 -0
- data/rbi/workos/profile.rbi +6 -0
- data/rbi/workos/user_api_key.rbi +72 -0
- data/rbi/workos/user_api_key_created_data_owner.rbi +36 -0
- data/rbi/workos/user_api_key_owner.rbi +36 -0
- data/rbi/workos/user_api_key_revoked_data_owner.rbi +36 -0
- data/rbi/workos/{api_key_with_value.rbi → user_api_key_with_value.rbi} +3 -3
- data/rbi/workos/user_api_key_with_value_owner.rbi +36 -0
- data/rbi/workos/user_management.rbi +31 -0
- data/rbi/workos/user_organization_membership.rbi +6 -0
- data/rbi/workos/user_organization_membership_base_list_data.rbi +6 -0
- data/rbi/workos/{role_assignment.rbi → user_role_assignment.rbi} +9 -3
- data/rbi/workos/{role_assignment_resource.rbi → user_role_assignment_resource.rbi} +1 -1
- data/rbi/workos/vault_byok_key_deleted.rbi +54 -0
- data/rbi/workos/vault_byok_key_deleted_data.rbi +30 -0
- data/script/docs +16 -0
- data/script/docs-serve +12 -0
- data/script/llms-txt +37 -0
- data/test/workos/test_actions.rb +9 -0
- data/test/workos/test_api_keys.rb +17 -17
- data/test/workos/test_authorization.rb +16 -0
- data/test/workos/test_base_client.rb +44 -0
- data/test/workos/test_encryptors_aes_gcm.rb +16 -1
- data/test/workos/test_model_round_trip.rb +278 -83
- data/test/workos/test_session.rb +43 -4
- data/test/workos/test_user_management.rb +25 -1
- data/test/workos/test_webhook_verify.rb +11 -0
- metadata +39 -33
- data/lib/workos/types/authorization_order.rb +0 -9
- data/lib/workos/types/connections_order.rb +0 -9
- data/lib/workos/types/directories_order.rb +0 -9
- data/lib/workos/types/directory_groups_order.rb +0 -9
- data/lib/workos/types/directory_users_order.rb +0 -9
- data/lib/workos/types/feature_flags_order.rb +0 -9
- data/lib/workos/types/organizations_api_keys_order.rb +0 -9
- data/lib/workos/types/organizations_feature_flags_order.rb +0 -9
- data/lib/workos/types/organizations_order.rb +0 -9
- data/lib/workos/types/permissions_order.rb +0 -9
- data/lib/workos/types/user_management_invitations_order.rb +0 -9
- data/lib/workos/types/user_management_multi_factor_authentication_order.rb +0 -9
- data/lib/workos/types/user_management_organization_membership_groups_order.rb +0 -9
- data/lib/workos/types/user_management_organization_membership_order.rb +0 -9
- data/lib/workos/types/user_management_users_authorized_applications_order.rb +0 -9
- data/lib/workos/types/user_management_users_feature_flags_order.rb +0 -9
- data/lib/workos/types/user_management_users_order.rb +0 -9
|
@@ -333,6 +333,13 @@ module WorkOS
|
|
|
333
333
|
end
|
|
334
334
|
def revoke_invitation(id:, request_options:); end
|
|
335
335
|
|
|
336
|
+
sig do
|
|
337
|
+
params(
|
|
338
|
+
request_options: T::Hash[Symbol, T.untyped]
|
|
339
|
+
).returns(WorkOS::JWTTemplateResponse)
|
|
340
|
+
end
|
|
341
|
+
def list_jwt_template(request_options:); end
|
|
342
|
+
|
|
336
343
|
sig do
|
|
337
344
|
params(
|
|
338
345
|
content: String,
|
|
@@ -452,5 +459,29 @@ module WorkOS
|
|
|
452
459
|
end
|
|
453
460
|
def delete_user_authorized_application(application_id:, user_id:, request_options:); end
|
|
454
461
|
|
|
462
|
+
sig do
|
|
463
|
+
params(
|
|
464
|
+
user_id: String,
|
|
465
|
+
before: T.nilable(String),
|
|
466
|
+
after: T.nilable(String),
|
|
467
|
+
limit: T.nilable(Integer),
|
|
468
|
+
order: T.nilable(String),
|
|
469
|
+
organization_id: T.nilable(String),
|
|
470
|
+
request_options: T::Hash[Symbol, T.untyped]
|
|
471
|
+
).returns(WorkOS::Types::ListStruct)
|
|
472
|
+
end
|
|
473
|
+
def list_user_api_keys(user_id:, before:, after:, limit:, order:, organization_id:, request_options:); end
|
|
474
|
+
|
|
475
|
+
sig do
|
|
476
|
+
params(
|
|
477
|
+
user_id: String,
|
|
478
|
+
name: String,
|
|
479
|
+
organization_id: String,
|
|
480
|
+
permissions: T.nilable(T::Array[String]),
|
|
481
|
+
request_options: T::Hash[Symbol, T.untyped]
|
|
482
|
+
).returns(WorkOS::UserApiKeyWithValue)
|
|
483
|
+
end
|
|
484
|
+
def create_user_api_key(user_id:, name:, organization_id:, permissions:, request_options:); end
|
|
485
|
+
|
|
455
486
|
end
|
|
456
487
|
end
|
|
@@ -75,6 +75,12 @@ module WorkOS
|
|
|
75
75
|
sig { params(value: WorkOS::SlimRole).returns(WorkOS::SlimRole) }
|
|
76
76
|
def role=(value); end
|
|
77
77
|
|
|
78
|
+
sig { returns(WorkOS::User) }
|
|
79
|
+
def user; end
|
|
80
|
+
|
|
81
|
+
sig { params(value: WorkOS::User).returns(WorkOS::User) }
|
|
82
|
+
def user=(value); end
|
|
83
|
+
|
|
78
84
|
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
79
85
|
def to_h; end
|
|
80
86
|
|
|
@@ -69,6 +69,12 @@ module WorkOS
|
|
|
69
69
|
sig { params(value: String).returns(String) }
|
|
70
70
|
def updated_at=(value); end
|
|
71
71
|
|
|
72
|
+
sig { returns(WorkOS::User) }
|
|
73
|
+
def user; end
|
|
74
|
+
|
|
75
|
+
sig { params(value: WorkOS::User).returns(WorkOS::User) }
|
|
76
|
+
def user=(value); end
|
|
77
|
+
|
|
72
78
|
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
73
79
|
def to_h; end
|
|
74
80
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# typed: strong
|
|
6
6
|
|
|
7
7
|
module WorkOS
|
|
8
|
-
class
|
|
8
|
+
class UserRoleAssignment
|
|
9
9
|
sig { params(json: T.any(String, T::Hash[Symbol, T.untyped])).void }
|
|
10
10
|
def initialize(json); end
|
|
11
11
|
|
|
@@ -21,16 +21,22 @@ module WorkOS
|
|
|
21
21
|
sig { params(value: String).returns(String) }
|
|
22
22
|
def id=(value); end
|
|
23
23
|
|
|
24
|
+
sig { returns(String) }
|
|
25
|
+
def organization_membership_id; end
|
|
26
|
+
|
|
27
|
+
sig { params(value: String).returns(String) }
|
|
28
|
+
def organization_membership_id=(value); end
|
|
29
|
+
|
|
24
30
|
sig { returns(WorkOS::SlimRole) }
|
|
25
31
|
def role; end
|
|
26
32
|
|
|
27
33
|
sig { params(value: WorkOS::SlimRole).returns(WorkOS::SlimRole) }
|
|
28
34
|
def role=(value); end
|
|
29
35
|
|
|
30
|
-
sig { returns(WorkOS::
|
|
36
|
+
sig { returns(WorkOS::UserRoleAssignmentResource) }
|
|
31
37
|
def resource; end
|
|
32
38
|
|
|
33
|
-
sig { params(value: WorkOS::
|
|
39
|
+
sig { params(value: WorkOS::UserRoleAssignmentResource).returns(WorkOS::UserRoleAssignmentResource) }
|
|
34
40
|
def resource=(value); end
|
|
35
41
|
|
|
36
42
|
sig { returns(String) }
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is auto-generated by oagen. Do not edit.
|
|
4
|
+
|
|
5
|
+
# typed: strong
|
|
6
|
+
|
|
7
|
+
module WorkOS
|
|
8
|
+
class VaultByokKeyDeleted
|
|
9
|
+
sig { params(json: T.any(String, T::Hash[Symbol, T.untyped])).void }
|
|
10
|
+
def initialize(json); end
|
|
11
|
+
|
|
12
|
+
sig { returns(String) }
|
|
13
|
+
def id; end
|
|
14
|
+
|
|
15
|
+
sig { params(value: String).returns(String) }
|
|
16
|
+
def id=(value); end
|
|
17
|
+
|
|
18
|
+
sig { returns(String) }
|
|
19
|
+
def event; end
|
|
20
|
+
|
|
21
|
+
sig { params(value: String).returns(String) }
|
|
22
|
+
def event=(value); end
|
|
23
|
+
|
|
24
|
+
sig { returns(WorkOS::VaultByokKeyDeletedData) }
|
|
25
|
+
def data; end
|
|
26
|
+
|
|
27
|
+
sig { params(value: WorkOS::VaultByokKeyDeletedData).returns(WorkOS::VaultByokKeyDeletedData) }
|
|
28
|
+
def data=(value); end
|
|
29
|
+
|
|
30
|
+
sig { returns(String) }
|
|
31
|
+
def created_at; end
|
|
32
|
+
|
|
33
|
+
sig { params(value: String).returns(String) }
|
|
34
|
+
def created_at=(value); end
|
|
35
|
+
|
|
36
|
+
sig { returns(T.nilable(WorkOS::EventContext)) }
|
|
37
|
+
def context; end
|
|
38
|
+
|
|
39
|
+
sig { params(value: T.nilable(WorkOS::EventContext)).returns(T.nilable(WorkOS::EventContext)) }
|
|
40
|
+
def context=(value); end
|
|
41
|
+
|
|
42
|
+
sig { returns(String) }
|
|
43
|
+
def object; end
|
|
44
|
+
|
|
45
|
+
sig { params(value: String).returns(String) }
|
|
46
|
+
def object=(value); end
|
|
47
|
+
|
|
48
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
49
|
+
def to_h; end
|
|
50
|
+
|
|
51
|
+
sig { params(args: T.untyped).returns(String) }
|
|
52
|
+
def to_json(*args); end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is auto-generated by oagen. Do not edit.
|
|
4
|
+
|
|
5
|
+
# typed: strong
|
|
6
|
+
|
|
7
|
+
module WorkOS
|
|
8
|
+
class VaultByokKeyDeletedData
|
|
9
|
+
sig { params(json: T.any(String, T::Hash[Symbol, T.untyped])).void }
|
|
10
|
+
def initialize(json); end
|
|
11
|
+
|
|
12
|
+
sig { returns(String) }
|
|
13
|
+
def organization_id; end
|
|
14
|
+
|
|
15
|
+
sig { params(value: String).returns(String) }
|
|
16
|
+
def organization_id=(value); end
|
|
17
|
+
|
|
18
|
+
sig { returns(String) }
|
|
19
|
+
def key_provider; end
|
|
20
|
+
|
|
21
|
+
sig { params(value: String).returns(String) }
|
|
22
|
+
def key_provider=(value); end
|
|
23
|
+
|
|
24
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
|
25
|
+
def to_h; end
|
|
26
|
+
|
|
27
|
+
sig { params(args: T.untyped).returns(String) }
|
|
28
|
+
def to_json(*args); end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/script/docs
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
cd "$(dirname "$0")/.."
|
|
4
|
+
bundle config set --local with 'docs'
|
|
5
|
+
bundle install
|
|
6
|
+
rm -rf docs/_site
|
|
7
|
+
# 1. Generate HTML docs (default YARD format).
|
|
8
|
+
bundle exec yard doc
|
|
9
|
+
# 2. Generate Markdown docs alongside the HTML, using the yard-markdown plugin.
|
|
10
|
+
# We point output at the same docs/_site directory so .md files land next to .html.
|
|
11
|
+
# --no-cache forces a re-parse so the markdown formatter sees fresh registry data.
|
|
12
|
+
# --plugin yard-markdown ensures the plugin is loaded without relying on ~/.yard/config.
|
|
13
|
+
bundle exec yard doc --plugin yard-markdown --format markdown --no-cache --output-dir docs/_site
|
|
14
|
+
# 3. Generate llms.txt (index) from the markdown output, so the published site
|
|
15
|
+
# is consumable by LLM tooling.
|
|
16
|
+
bundle exec ./script/llms-txt
|
data/script/docs-serve
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
set -eu
|
|
3
|
+
cd "$(dirname "$0")/.."
|
|
4
|
+
bundle config set --local with 'docs'
|
|
5
|
+
bundle install --quiet
|
|
6
|
+
if [ "${1:-}" = "--static" ]; then
|
|
7
|
+
if [ ! -d docs/_site ]; then
|
|
8
|
+
./script/docs
|
|
9
|
+
fi
|
|
10
|
+
exec bundle exec ruby -run -e httpd -- docs/_site -p 4000
|
|
11
|
+
fi
|
|
12
|
+
exec bundle exec yard server --reload --port 4000
|
data/script/llms-txt
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Generates llms.txt (curated index) from the Markdown docs produced by
|
|
5
|
+
# `yard --format markdown` in docs/_site. See https://llmstxt.org for the format.
|
|
6
|
+
|
|
7
|
+
require "pathname"
|
|
8
|
+
|
|
9
|
+
ROOT = Pathname.new(__dir__).join("..").expand_path
|
|
10
|
+
SITE = ROOT.join("docs/_site")
|
|
11
|
+
require ROOT.join("lib/workos/version").to_s
|
|
12
|
+
|
|
13
|
+
abort "docs/_site is missing — run script/docs first" unless SITE.directory?
|
|
14
|
+
|
|
15
|
+
md_files = Pathname.glob(SITE.join("**/*.md")).sort_by { |p| p.relative_path_from(SITE).to_s }
|
|
16
|
+
|
|
17
|
+
title_for = lambda do |path|
|
|
18
|
+
first_heading = path.each_line.lazy.map(&:strip).find { |l| l.start_with?("# ") }
|
|
19
|
+
first_heading ? first_heading.sub(/^#\s+/, "").sub(/\s*<a id=.*?<\/a>\s*$/, "").strip : path.basename(".md").to_s
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
index_lines = []
|
|
23
|
+
index_lines << "# WorkOS Ruby SDK v#{WorkOS::VERSION}"
|
|
24
|
+
index_lines << ""
|
|
25
|
+
index_lines << "> API client for WorkOS. This file indexes the auto-generated YARD documentation for the `workos` gem so language models can locate per-class references."
|
|
26
|
+
index_lines << ""
|
|
27
|
+
index_lines << "## API Reference"
|
|
28
|
+
index_lines << ""
|
|
29
|
+
md_files.each do |path|
|
|
30
|
+
rel = path.relative_path_from(SITE).to_s
|
|
31
|
+
index_lines << "- [#{title_for.call(path)}](#{rel})"
|
|
32
|
+
end
|
|
33
|
+
index_lines << ""
|
|
34
|
+
|
|
35
|
+
SITE.join("llms.txt").write(index_lines.join("\n"))
|
|
36
|
+
|
|
37
|
+
puts "Wrote #{SITE.join("llms.txt")} (#{md_files.size} entries)"
|
data/test/workos/test_actions.rb
CHANGED
|
@@ -49,6 +49,15 @@ class ActionsTest < Minitest::Test
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
def test_verify_header_raises_on_future_timestamp
|
|
53
|
+
payload = '{"x":1}'
|
|
54
|
+
future_ts = now_ms + 60_000 # 60s ahead, beyond default 30s tolerance
|
|
55
|
+
sig = OpenSSL::HMAC.hexdigest("SHA256", SECRET, "#{future_ts}.#{payload}")
|
|
56
|
+
assert_raises(WorkOS::SignatureVerificationError) do
|
|
57
|
+
@actions.verify_header(payload: payload, sig_header: "t=#{future_ts}, v1=#{sig}", secret: SECRET)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
52
61
|
def test_sign_response_authentication_allow
|
|
53
62
|
resp = @actions.sign_response(action_type: "authentication", verdict: "Allow", secret: SECRET)
|
|
54
63
|
assert_equal "authentication_action_response", resp["object"]
|
|
@@ -11,20 +11,6 @@ class ApiKeysTest < Minitest::Test
|
|
|
11
11
|
@client = WorkOS::Client.new(api_key: "sk_test_123")
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def test_create_validation_returns_expected_result
|
|
15
|
-
stub_request(:post, %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)})
|
|
16
|
-
.to_return(body: "{}", status: 200)
|
|
17
|
-
result = @client.api_keys.create_validation(value: "stub")
|
|
18
|
-
refute_nil result
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def test_delete_api_key_returns_expected_result
|
|
22
|
-
stub_request(:delete, %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)})
|
|
23
|
-
.to_return(body: "{}", status: 200)
|
|
24
|
-
result = @client.api_keys.delete_api_key(id: "stub")
|
|
25
|
-
assert_nil result
|
|
26
|
-
end
|
|
27
|
-
|
|
28
14
|
def test_list_organization_api_keys_returns_expected_result
|
|
29
15
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)})
|
|
30
16
|
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
@@ -39,12 +25,26 @@ class ApiKeysTest < Minitest::Test
|
|
|
39
25
|
refute_nil result
|
|
40
26
|
end
|
|
41
27
|
|
|
28
|
+
def test_create_validation_returns_expected_result
|
|
29
|
+
stub_request(:post, %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)})
|
|
30
|
+
.to_return(body: "{}", status: 200)
|
|
31
|
+
result = @client.api_keys.create_validation(value: "stub")
|
|
32
|
+
refute_nil result
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_delete_api_key_returns_expected_result
|
|
36
|
+
stub_request(:delete, %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)})
|
|
37
|
+
.to_return(body: "{}", status: 200)
|
|
38
|
+
result = @client.api_keys.delete_api_key(id: "stub")
|
|
39
|
+
assert_nil result
|
|
40
|
+
end
|
|
41
|
+
|
|
42
42
|
# Parameterized authentication error tests (one per endpoint).
|
|
43
43
|
[
|
|
44
|
-
{name: :create_validation, verb: :post, url: %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)}, args: {value: "stub"}},
|
|
45
|
-
{name: :delete_api_key, verb: :delete, url: %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)}, args: {id: "stub"}},
|
|
46
44
|
{name: :list_organization_api_keys, verb: :get, url: %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)}, args: {organization_id: "stub"}},
|
|
47
|
-
{name: :create_organization_api_key, verb: :post, url: %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)}, args: {organization_id: "stub", name: "stub"}}
|
|
45
|
+
{name: :create_organization_api_key, verb: :post, url: %r{\Ahttps://api\.workos\.com/organizations/stub/api_keys(\?|\z)}, args: {organization_id: "stub", name: "stub"}},
|
|
46
|
+
{name: :create_validation, verb: :post, url: %r{\Ahttps://api\.workos\.com/api_keys/validations(\?|\z)}, args: {value: "stub"}},
|
|
47
|
+
{name: :delete_api_key, verb: :delete, url: %r{\Ahttps://api\.workos\.com/api_keys/stub(\?|\z)}, args: {id: "stub"}}
|
|
48
48
|
].each do |spec|
|
|
49
49
|
define_method("test_#{spec[:name]}_raises_authentication_error_on_401") do
|
|
50
50
|
stub_request(spec[:verb], spec[:url])
|
|
@@ -192,6 +192,13 @@ class AuthorizationTest < Minitest::Test
|
|
|
192
192
|
assert_kind_of WorkOS::Types::ListStruct, result
|
|
193
193
|
end
|
|
194
194
|
|
|
195
|
+
def test_list_role_assignments_for_resource_by_external_id_returns_expected_result
|
|
196
|
+
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/role_assignments(\?|\z)})
|
|
197
|
+
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
198
|
+
result = @client.authorization.list_role_assignments_for_resource_by_external_id(organization_id: "stub", resource_type_slug: "stub", external_id: "stub")
|
|
199
|
+
assert_kind_of WorkOS::Types::ListStruct, result
|
|
200
|
+
end
|
|
201
|
+
|
|
195
202
|
def test_list_resources_returns_expected_result
|
|
196
203
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)})
|
|
197
204
|
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
@@ -259,6 +266,13 @@ class AuthorizationTest < Minitest::Test
|
|
|
259
266
|
assert_kind_of WorkOS::Types::ListStruct, result
|
|
260
267
|
end
|
|
261
268
|
|
|
269
|
+
def test_list_role_assignments_for_resource_returns_expected_result
|
|
270
|
+
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/resources/stub/role_assignments(\?|\z)})
|
|
271
|
+
.to_return(body: '{"data": [], "list_metadata": {}}', status: 200)
|
|
272
|
+
result = @client.authorization.list_role_assignments_for_resource(resource_id: "stub")
|
|
273
|
+
assert_kind_of WorkOS::Types::ListStruct, result
|
|
274
|
+
end
|
|
275
|
+
|
|
262
276
|
def test_list_environment_roles_returns_expected_result
|
|
263
277
|
stub_request(:get, %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)})
|
|
264
278
|
.to_return(body: "{}", status: 200)
|
|
@@ -358,12 +372,14 @@ class AuthorizationTest < Minitest::Test
|
|
|
358
372
|
{name: :update_resource_by_external_id, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
359
373
|
{name: :delete_resource_by_external_id, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
360
374
|
{name: :list_memberships_for_resource_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/organization_memberships(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub", permission_slug: "stub"}},
|
|
375
|
+
{name: :list_role_assignments_for_resource_by_external_id, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/organizations/stub/resources/stub/stub/role_assignments(\?|\z)}, args: {organization_id: "stub", resource_type_slug: "stub", external_id: "stub"}},
|
|
361
376
|
{name: :list_resources, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {parent: WorkOS::Authorization::ParentById.new(parent_resource_id: "stub")}},
|
|
362
377
|
{name: :create_resource, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/resources(\?|\z)}, args: {external_id: "stub", name: "stub", resource_type_slug: "stub", organization_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
363
378
|
{name: :get_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
364
379
|
{name: :update_resource, verb: :patch, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub", parent_resource: WorkOS::Authorization::ParentResourceById.new(parent_resource_id: "stub")}},
|
|
365
380
|
{name: :delete_resource, verb: :delete, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub(\?|\z)}, args: {resource_id: "stub"}},
|
|
366
381
|
{name: :list_memberships_for_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub/organization_memberships(\?|\z)}, args: {resource_id: "stub", permission_slug: "stub"}},
|
|
382
|
+
{name: :list_role_assignments_for_resource, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/resources/stub/role_assignments(\?|\z)}, args: {resource_id: "stub"}},
|
|
367
383
|
{name: :list_environment_roles, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)}},
|
|
368
384
|
{name: :create_environment_role, verb: :post, url: %r{\Ahttps://api\.workos\.com/authorization/roles(\?|\z)}, args: {slug: "stub", name: "stub"}},
|
|
369
385
|
{name: :get_environment_role, verb: :get, url: %r{\Ahttps://api\.workos\.com/authorization/roles/stub(\?|\z)}, args: {slug: "stub"}},
|
|
@@ -170,4 +170,48 @@ class BaseClientTest < Minitest::Test
|
|
|
170
170
|
assert evict.finished
|
|
171
171
|
refute keep.finished
|
|
172
172
|
end
|
|
173
|
+
|
|
174
|
+
def test_redact_path_strips_invitation_token_segment
|
|
175
|
+
redacted = @client.send(:redact_path, "/user_management/invitations/by_token/invtoken_secret123")
|
|
176
|
+
assert_equal "/user_management/invitations/by_token/[REDACTED]", redacted
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def test_redact_path_strips_magic_auth_token_segment
|
|
180
|
+
redacted = @client.send(:redact_path, "/user_management/magic_auth/magic_secret/extra")
|
|
181
|
+
assert_equal "/user_management/magic_auth/[REDACTED]/[REDACTED]", redacted
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def test_redact_path_preserves_non_token_paths
|
|
185
|
+
assert_equal "/organizations/org_123", @client.send(:redact_path, "/organizations/org_123")
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def test_redact_path_preserves_query_string
|
|
189
|
+
redacted = @client.send(:redact_path, "/user_management/invitations/by_token/secret?foo=bar")
|
|
190
|
+
assert_equal "/user_management/invitations/by_token/[REDACTED]?foo=bar", redacted
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def test_redact_path_handles_nil_and_empty
|
|
194
|
+
assert_nil @client.send(:redact_path, nil)
|
|
195
|
+
assert_equal "", @client.send(:redact_path, "")
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_redact_path_scrubs_sensitive_query_params
|
|
199
|
+
redacted = @client.send(:redact_path, "/user_management/sessions/logout?session_id=ses_abc123&return_to=https://app.example.com")
|
|
200
|
+
assert_equal "/user_management/sessions/logout?session_id=[REDACTED]&return_to=https://app.example.com", redacted
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def test_redact_path_scrubs_authorize_code_query_param
|
|
204
|
+
redacted = @client.send(:redact_path, "/user_management/authorize?client_id=client_1&code=auth_code_secret&state=xyz")
|
|
205
|
+
assert_equal "/user_management/authorize?client_id=client_1&code=[REDACTED]&state=xyz", redacted
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def test_redact_path_leaves_non_sensitive_query_params_untouched
|
|
209
|
+
redacted = @client.send(:redact_path, "/user_management/users?limit=10&order=desc")
|
|
210
|
+
assert_equal "/user_management/users?limit=10&order=desc", redacted
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def test_redact_path_scrubs_query_alongside_path_segment_redaction
|
|
214
|
+
redacted = @client.send(:redact_path, "/user_management/magic_auth/magic_secret?token=qs_token")
|
|
215
|
+
assert_equal "/user_management/magic_auth/[REDACTED]?token=[REDACTED]", redacted
|
|
216
|
+
end
|
|
173
217
|
end
|
|
@@ -28,11 +28,26 @@ class EncryptorsAesGcmTest < Minitest::Test
|
|
|
28
28
|
|
|
29
29
|
def test_unseal_with_wrong_key_raises
|
|
30
30
|
sealed = @enc.seal({"x" => 1}, PASSWORD)
|
|
31
|
+
# Wrong key is the same length (>= 32 bytes) so the length guard doesn't
|
|
32
|
+
# short-circuit; we want to assert the underlying cipher rejection.
|
|
31
33
|
assert_raises(OpenSSL::Cipher::CipherError) do
|
|
32
|
-
@enc.unseal(sealed, "wrong-password")
|
|
34
|
+
@enc.unseal(sealed, "wrong-cookie-password-32-bytes--")
|
|
33
35
|
end
|
|
34
36
|
end
|
|
35
37
|
|
|
38
|
+
def test_unseal_rejects_short_key
|
|
39
|
+
sealed = @enc.seal({"x" => 1}, PASSWORD)
|
|
40
|
+
assert_raises(ArgumentError) do
|
|
41
|
+
@enc.unseal(sealed, "too-short")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_seal_rejects_short_key
|
|
46
|
+
assert_raises(ArgumentError) { @enc.seal({"x" => 1}, "too-short") }
|
|
47
|
+
assert_raises(ArgumentError) { @enc.seal({"x" => 1}, nil) }
|
|
48
|
+
assert_raises(ArgumentError) { @enc.seal({"x" => 1}, "") }
|
|
49
|
+
end
|
|
50
|
+
|
|
36
51
|
def test_unseal_rejects_short_payload
|
|
37
52
|
assert_raises(ArgumentError) do
|
|
38
53
|
@enc.unseal(Base64.strict_encode64("short"), PASSWORD)
|