btps_client 1.0.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 (38) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +444 -0
  3. data/lib/btps_client/api_operations/actionable.rb +22 -0
  4. data/lib/btps_client/api_operations/creatable.rb +16 -0
  5. data/lib/btps_client/api_operations/deletable.rb +15 -0
  6. data/lib/btps_client/api_operations/listable.rb +16 -0
  7. data/lib/btps_client/api_operations/movable.rb +17 -0
  8. data/lib/btps_client/api_operations/nested_listable.rb +23 -0
  9. data/lib/btps_client/api_operations/retrievable.rb +15 -0
  10. data/lib/btps_client/api_operations/scalar_creatable.rb +31 -0
  11. data/lib/btps_client/api_operations/searchable.rb +16 -0
  12. data/lib/btps_client/api_operations/updatable.rb +16 -0
  13. data/lib/btps_client/api_operations/uploadable.rb +29 -0
  14. data/lib/btps_client/api_requestor.rb +143 -0
  15. data/lib/btps_client/api_resource.rb +45 -0
  16. data/lib/btps_client/btps_object.rb +58 -0
  17. data/lib/btps_client/client.rb +37 -0
  18. data/lib/btps_client/configuration.rb +71 -0
  19. data/lib/btps_client/errors.rb +39 -0
  20. data/lib/btps_client/resources/credential.rb +98 -0
  21. data/lib/btps_client/resources/folder.rb +36 -0
  22. data/lib/btps_client/resources/managed_account.rb +97 -0
  23. data/lib/btps_client/resources/request.rb +107 -0
  24. data/lib/btps_client/resources/safe.rb +77 -0
  25. data/lib/btps_client/resources/secret.rb +179 -0
  26. data/lib/btps_client/schema_builder.rb +50 -0
  27. data/lib/btps_client/services/auth_service.rb +57 -0
  28. data/lib/btps_client/services/credentials_service.rb +36 -0
  29. data/lib/btps_client/services/folders_service.rb +37 -0
  30. data/lib/btps_client/services/managed_accounts_service.rb +48 -0
  31. data/lib/btps_client/services/requests_service.rb +44 -0
  32. data/lib/btps_client/services/safes_service.rb +48 -0
  33. data/lib/btps_client/services/secrets_safe_service.rb +25 -0
  34. data/lib/btps_client/services/secrets_service.rb +96 -0
  35. data/lib/btps_client/validator.rb +129 -0
  36. data/lib/btps_client/version.rb +5 -0
  37. data/lib/btps_client.rb +64 -0
  38. metadata +183 -0
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BtpsClient
4
+ module Services
5
+ # Thin façade over Resources::Safe.
6
+ class SafesService
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ def list(params = {})
12
+ Resources::Safe.list(params, config: @config)
13
+ end
14
+
15
+ def retrieve(id)
16
+ Resources::Safe.retrieve(id, config: @config)
17
+ end
18
+
19
+ def create(params)
20
+ Resources::Safe.create(params, config: @config)
21
+ end
22
+
23
+ def update(id, params)
24
+ Resources::Safe.update(id, params, config: @config)
25
+ end
26
+
27
+ def delete(id)
28
+ Resources::Safe.delete(id, config: @config)
29
+ end
30
+
31
+ def all_permissions
32
+ Resources::Safe.all_permissions(config: @config)
33
+ end
34
+
35
+ def permissions(id)
36
+ Resources::Safe.permissions(id, config: @config)
37
+ end
38
+
39
+ def update_permissions(id, params)
40
+ Resources::Safe.update_permissions(id, params, config: @config)
41
+ end
42
+
43
+ def revoke_permissions(id, params)
44
+ Resources::Safe.revoke_permissions(id, params, config: @config)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BtpsClient
4
+ module Services
5
+ # Aggregator service — groups Folders, Safes, and Secrets under one namespace.
6
+ # Access via client.secrets_safe.folders / .safes / .secrets
7
+ class SecretsSafeService
8
+ def initialize(config)
9
+ @config = config
10
+ end
11
+
12
+ def folders
13
+ @folders ||= FoldersService.new(@config)
14
+ end
15
+
16
+ def safes
17
+ @safes ||= SafesService.new(@config)
18
+ end
19
+
20
+ def secrets
21
+ @secrets ||= SecretsService.new(@config)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BtpsClient
4
+ module Services
5
+ # Thin façade over Resources::Secret.
6
+ class SecretsService
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+
11
+ # Standard mixin operations
12
+ def list(params = {})
13
+ Resources::Secret.list(params, config: @config)
14
+ end
15
+
16
+ def retrieve(id)
17
+ Resources::Secret.retrieve(id, config: @config)
18
+ end
19
+
20
+ def update(id, params)
21
+ Resources::Secret.update(id, params, config: @config)
22
+ end
23
+
24
+ def delete(id)
25
+ Resources::Secret.delete(id, config: @config)
26
+ end
27
+
28
+ # Folder-scoped creates
29
+ def create_in_folder(folder_id, params)
30
+ Resources::Secret.create_in_folder(folder_id, params, config: @config)
31
+ end
32
+
33
+ def create_text_in_folder(folder_id, params)
34
+ Resources::Secret.create_text_in_folder(folder_id, params, config: @config)
35
+ end
36
+
37
+ def create_file_in_folder(folder_id, file:, metadata: {})
38
+ Resources::Secret.create_file_in_folder(folder_id, file: file, metadata: metadata, config: @config)
39
+ end
40
+
41
+ # Folder-scoped list
42
+ def list_in_folder(folder_id, params = {})
43
+ Resources::Secret.list_in_folder(folder_id, params, config: @config)
44
+ end
45
+
46
+ # Typed retrieve
47
+ def retrieve_text(id)
48
+ Resources::Secret.retrieve_text(id, config: @config)
49
+ end
50
+
51
+ def retrieve_file(id)
52
+ Resources::Secret.retrieve_file(id, config: @config)
53
+ end
54
+
55
+ def download_file(id)
56
+ Resources::Secret.download_file(id, config: @config)
57
+ end
58
+
59
+ # Typed updates
60
+ def update_text(id, params)
61
+ Resources::Secret.update_text(id, params, config: @config)
62
+ end
63
+
64
+ def update_file(id, file:, metadata: {})
65
+ Resources::Secret.update_file(id, file: file, metadata: metadata, config: @config)
66
+ end
67
+
68
+ # Bulk move
69
+ def move(params)
70
+ Resources::Secret.move(params, config: @config)
71
+ end
72
+
73
+ # CSV upload
74
+ def upload_csv(folder_id, file:)
75
+ Resources::Secret.upload_csv(folder_id, file: file, config: @config)
76
+ end
77
+
78
+ # Shares
79
+ def shares(secret_id)
80
+ Resources::Secret.shares(secret_id, config: @config)
81
+ end
82
+
83
+ def share_to_folder(secret_id, folder_id)
84
+ Resources::Secret.share_to_folder(secret_id, folder_id, config: @config)
85
+ end
86
+
87
+ def unshare_from_folder(secret_id, folder_id)
88
+ Resources::Secret.unshare_from_folder(secret_id, folder_id, config: @config)
89
+ end
90
+
91
+ def unshare_all(secret_id)
92
+ Resources::Secret.unshare_all(secret_id, config: @config)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BtpsClient
4
+ # Pure validation engine. Receives a schema hash built by SchemaBuilder
5
+ # (via the param_schema macro on ApiResource subclasses) and validates
6
+ # params against it before any HTTP request is sent.
7
+ #
8
+ # No schema registry lives here — each resource owns its constraints.
9
+ #
10
+ # Usage (automatic via param_schema + mixins):
11
+ # Validator.validate!(schema_for(:create), { Name: 'Ops' })
12
+ # # => nil on success, raises BtpsClient::ValidationError on failure
13
+ #
14
+ # Error messages list ALL failures at once so callers can fix everything
15
+ # in one go rather than one error per request.
16
+ class Validator
17
+ UUID_RE = /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i.freeze
18
+
19
+ # Validates +params+ against a schema hash produced by SchemaBuilder#to_h.
20
+ #
21
+ # @param schema [Hash, nil] { required: [...], fields: { name => rules } };
22
+ # nil is a no-op (no schema declared for this operation).
23
+ # @param params [Hash] request body; accepts symbol or string keys.
24
+ # @return [nil]
25
+ # @raise [BtpsClient::ValidationError] lists ALL failures in one raise.
26
+ def self.validate!(schema, params)
27
+ return unless schema
28
+
29
+ # Normalise to string keys so callers can use either :Name or 'Name'
30
+ normalized = params.transform_keys(&:to_s)
31
+ errors = []
32
+
33
+ check_required(normalized, schema[:required], errors)
34
+ check_fields(normalized, schema[:fields], errors)
35
+
36
+ return if errors.empty?
37
+
38
+ raise ValidationError.new(
39
+ "Validation failed: #{errors.join('; ')}",
40
+ http_status: nil, http_body: nil
41
+ )
42
+ end
43
+
44
+ class << self
45
+ private
46
+
47
+ def check_required(params, required_fields, errors)
48
+ (required_fields || []).each do |field|
49
+ errors << "#{field} is required" if params[field].nil?
50
+ end
51
+ end
52
+
53
+ def check_fields(params, fields, errors)
54
+ (fields || {}).each do |field, rules|
55
+ val = params[field]
56
+ next if handle_nil_field(field, val, params, rules, errors)
57
+
58
+ check_type(field, val, rules, errors)
59
+ check_length(field, val, rules, errors)
60
+ check_range(field, val, rules, errors)
61
+ check_format(field, val, rules, errors)
62
+ check_enum(field, val, rules, errors)
63
+ end
64
+ end
65
+
66
+ # rubocop:disable Naming/PredicateMethod
67
+ def handle_nil_field(field, val, params, rules, errors)
68
+ return false unless val.nil?
69
+ return true unless params.key?(field) # absent optional field
70
+ return true if rules[:nullable] # explicit nil allowed
71
+
72
+ errors << "#{field} must not be null" # explicit nil, non-nullable
73
+ true
74
+ end
75
+ # rubocop:enable Naming/PredicateMethod
76
+
77
+ def check_type(field, val, rules, errors)
78
+ expected = rules[:type]
79
+ return unless expected
80
+
81
+ ok = case expected
82
+ when :string then val.is_a?(String)
83
+ when :integer then val.is_a?(Integer)
84
+ when :array then val.is_a?(Array)
85
+ when :boolean then [true, false].include?(val)
86
+ else true
87
+ end
88
+ errors << "#{field} must be a #{expected}" unless ok
89
+ end
90
+
91
+ def check_length(field, val, rules, errors)
92
+ return unless val.is_a?(String)
93
+
94
+ min = rules[:min_length]
95
+ max = rules[:max_length]
96
+ errors << "#{field} must be at least #{min} character(s)" if min && val.length < min
97
+ return unless max && val.length > max
98
+
99
+ errors << "#{field} must be at most #{max} character(s) (got #{val.length})"
100
+ end
101
+
102
+ def check_range(field, val, rules, errors)
103
+ return unless val.is_a?(Integer)
104
+
105
+ min = rules[:minimum]
106
+ max = rules[:maximum]
107
+ errors << "#{field} must be >= #{min}" if min && val < min
108
+ errors << "#{field} must be <= #{max}" if max && val > max
109
+ end
110
+
111
+ def check_format(field, val, rules, errors)
112
+ return unless val.is_a?(String) && rules[:format] == :uuid
113
+
114
+ return if val.match?(UUID_RE)
115
+
116
+ errors << "#{field} must be a valid UUID (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)"
117
+ end
118
+
119
+ def check_enum(field, val, rules, errors)
120
+ allowed = rules[:values]
121
+ return unless allowed
122
+
123
+ return if allowed.include?(val)
124
+
125
+ errors << "#{field} must be one of: #{allowed.join(', ')} (got #{val.inspect})"
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BtpsClient
4
+ VERSION = '1.0.0'
5
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'btps_client/version'
4
+ require_relative 'btps_client/errors'
5
+ require_relative 'btps_client/configuration'
6
+ require_relative 'btps_client/validator'
7
+ require_relative 'btps_client/schema_builder'
8
+ require_relative 'btps_client/btps_object'
9
+ require_relative 'btps_client/api_resource'
10
+ require_relative 'btps_client/api_requestor'
11
+
12
+ # Mixins
13
+ require_relative 'btps_client/api_operations/listable'
14
+ require_relative 'btps_client/api_operations/retrievable'
15
+ require_relative 'btps_client/api_operations/creatable'
16
+ require_relative 'btps_client/api_operations/scalar_creatable'
17
+ require_relative 'btps_client/api_operations/updatable'
18
+ require_relative 'btps_client/api_operations/deletable'
19
+ require_relative 'btps_client/api_operations/movable'
20
+ require_relative 'btps_client/api_operations/searchable'
21
+ require_relative 'btps_client/api_operations/uploadable'
22
+ require_relative 'btps_client/api_operations/actionable'
23
+ require_relative 'btps_client/api_operations/nested_listable'
24
+
25
+ # Resources
26
+ require_relative 'btps_client/resources/folder'
27
+ require_relative 'btps_client/resources/safe'
28
+ require_relative 'btps_client/resources/secret'
29
+ require_relative 'btps_client/resources/managed_account'
30
+ require_relative 'btps_client/resources/request'
31
+ require_relative 'btps_client/resources/credential'
32
+
33
+ # Services
34
+ require_relative 'btps_client/services/auth_service'
35
+ require_relative 'btps_client/services/folders_service'
36
+ require_relative 'btps_client/services/safes_service'
37
+ require_relative 'btps_client/services/secrets_service'
38
+ require_relative 'btps_client/services/secrets_safe_service'
39
+ require_relative 'btps_client/services/managed_accounts_service'
40
+ require_relative 'btps_client/services/requests_service'
41
+ require_relative 'btps_client/services/credentials_service'
42
+
43
+ # Client
44
+ require_relative 'btps_client/client'
45
+
46
+ module BtpsClient
47
+ class << self
48
+ def configure
49
+ yield(configuration)
50
+ end
51
+
52
+ def configuration
53
+ @configuration ||= Configuration.new
54
+ end
55
+
56
+ def config
57
+ configuration
58
+ end
59
+
60
+ def reset!
61
+ @configuration = nil
62
+ end
63
+ end
64
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: btps_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - BeyondTrust
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-03-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: typhoeus
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.1
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.0.1
33
+ - !ruby/object:Gem::Dependency
34
+ name: rspec
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '3.6'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.6'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '13.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '13.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rubocop
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: pry-byebug
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: simplecov
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: simplecov_json_formatter
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ description: A production-quality Ruby SDK for the BeyondTrust Password Safe REST
118
+ API v3, covering Auth and Secrets Safe (Folders, Safes, Secrets).
119
+ email:
120
+ executables: []
121
+ extensions: []
122
+ extra_rdoc_files: []
123
+ files:
124
+ - README.md
125
+ - lib/btps_client.rb
126
+ - lib/btps_client/api_operations/actionable.rb
127
+ - lib/btps_client/api_operations/creatable.rb
128
+ - lib/btps_client/api_operations/deletable.rb
129
+ - lib/btps_client/api_operations/listable.rb
130
+ - lib/btps_client/api_operations/movable.rb
131
+ - lib/btps_client/api_operations/nested_listable.rb
132
+ - lib/btps_client/api_operations/retrievable.rb
133
+ - lib/btps_client/api_operations/scalar_creatable.rb
134
+ - lib/btps_client/api_operations/searchable.rb
135
+ - lib/btps_client/api_operations/updatable.rb
136
+ - lib/btps_client/api_operations/uploadable.rb
137
+ - lib/btps_client/api_requestor.rb
138
+ - lib/btps_client/api_resource.rb
139
+ - lib/btps_client/btps_object.rb
140
+ - lib/btps_client/client.rb
141
+ - lib/btps_client/configuration.rb
142
+ - lib/btps_client/errors.rb
143
+ - lib/btps_client/resources/credential.rb
144
+ - lib/btps_client/resources/folder.rb
145
+ - lib/btps_client/resources/managed_account.rb
146
+ - lib/btps_client/resources/request.rb
147
+ - lib/btps_client/resources/safe.rb
148
+ - lib/btps_client/resources/secret.rb
149
+ - lib/btps_client/schema_builder.rb
150
+ - lib/btps_client/services/auth_service.rb
151
+ - lib/btps_client/services/credentials_service.rb
152
+ - lib/btps_client/services/folders_service.rb
153
+ - lib/btps_client/services/managed_accounts_service.rb
154
+ - lib/btps_client/services/requests_service.rb
155
+ - lib/btps_client/services/safes_service.rb
156
+ - lib/btps_client/services/secrets_safe_service.rb
157
+ - lib/btps_client/services/secrets_service.rb
158
+ - lib/btps_client/validator.rb
159
+ - lib/btps_client/version.rb
160
+ homepage:
161
+ licenses:
162
+ - MIT
163
+ metadata: {}
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '2.7'
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubygems_version: 3.5.22
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Ruby SDK for BeyondTrust Password Safe API v3
183
+ test_files: []